Cleaning up the Upcoming Events block in Drupal

We use the Events module to manage workshops here in the Teaching & Learning Centre, and use the “Upcoming Events” block to display the next few workshops on our website. Works great, but the default text leaves a bit to be desired. By default, it shows the event title, and “(2 days)” – which indicates that the event begins in 2 days.

But, it could also mean that the event lasts for 2 days.

So, I just added a trivial change to the event.module file, adding the following line of code at line 1847 (on my copy of the file, which was checked out on June 4, 2007):

$timeleft = 'starts in ' . $timeleft;

That changes the text indicator in the “Upcoming Events” block to read:

(starts in 2 days)

Which is much clearer in meaning. Easy peasy. I just have to remember to edit the module after updating, if this doesn’t make it in…

Drupal Debugging – Fun with CCK, Links and Token.module

I had to debug our TLC website this morning, as it was pointed out to me that parts were misbehaving, and that some content hadn’t survived the upgrade from Drupal 4.7 to Drupal 5.2. The missing content was easy, for the most part. It’s just a matter of renaming the tables to use the content_TABLE format expected by the current CCK module. The exact table names that are expected are listed in the node_type table, under the “orig_type” field – just prepend “content_” to the “orig_type” value for the table name, and CCK should find everything just fine.

One of the CCK content types used the weburl field type under Drupal 4.7, but this has apparently been replaced by “link” in Drupal 5’s version of CCK. That’s fine, I’ll just swap out the data. Shouldn’t be too bad.

What got puzzling, though, was that after switching to link, I was getting segmentation faults on the webserver every time I tried to view, save, or template a CCK content type containing a link. WTF? At first, I didn’t make the connection that it was link that was causing problems. Eventually, I created a “test” CCK content type, containing the same fields as the offending content type (every time I tried to view anything in our “Simple Resource” content type, hell was unleashed). I reproduced the same set of fields, and BOOM, Simple Resource was also bringing down the server. So, I started removing fields. Didn’t take long, since the content type had a total of 2 fields. I started with the Link field. And the content saved, viewed, and templated just fine.

AHAH! It’s something wrong with Link! Maybe it’s trying to validate the URL? Maybe it’s trying to download the content at the other end of the URL to do some processing?

Nope. Turns out, Link may use the token.module to parse out bits of the URL. But token.module was getting caught in a recursive loop. I had to install token.module to support the current version of pathauto.module – I need that, so I can’t disable token.module. Turns out, there’s an easy way to avoid this recursion-killing-the-webserver segmentation fault problem. In the CCK definition for the link field, just uncheck the “Allow Tokens” option. Yeah. It’s that easy. But it took me all frigging morning to figure out what the problem was, and about 5 seconds to fix it once it was identified.

Links that were useful in diagnosing and solving this:

Updating a Large Scale Drupal Multisite Installation?

In the Teaching & Learning Centre, we run a couple of servers, each with a dozen or so Drupal sites installed in a multisite configuration (one copy of Drupal, using the sites directory to respond to various URLs). With every update to core or modules, the update.php file needs to be called for each site. That’s not too onerous, but is a bit of a PITA.

Our central IT shop at the University of Calgary has a whole ‘nother problem. Their Drupal server is currently running well over 400 sites. So, calling update.php on each one effectively means having a bunch of folks (students? interns?) clicking through the update.php screens for each site. Say it takes maybe 5 minutes per site, that’s over 30 hours of labour to update all sites. And new sites are added every day.

There has to be a better way. I was hoping Sympal Scripts had some magic fu, but came up empty. Are there any secret tricks to calling update.php on each site quasi-automatically for a large-scale Drupal multisite installation?

Fun with Drupal Upgrades

Our main Teaching & Learning Centre website runs on Drupal, with extensive use of CCK, Views, Events and Signup modules. The site had been running on the Drupal 4.7, with only security patches applied. But it was starting to act up (content was suddenly not showing up), so I decided to pull everything up to the current 5.2 line, with updated modules. It’s an easy enough upgrade. When it works.

The CCK update appears to have really botched things. As in, most of our custom content types are now missing data for several of their fields. The data’s safe – I can see it in the database – but it’s not showing up when viewing or editing the nodes. Annoying.

So, my task over the next couple of days (hopefully much shorter than that) is to debug wtf went wrong, and figure out how to manually upgrade the various CCK database tables from wherever they were to where they need to be for 5.2. Fun stuff.

Also, the embedded Views have decided to go TU, so I get to debug wtf is going on there, as well.

Thankfully, I have backups of the data, so can play a bit if needed, but I need to leave the main site up and live to support workshop registrations while I fix things. It’s taken much of today to get the site to the state it’s in now. Haven’t even had a chance to check all of my feeds yet. The horrors!

I may need to dig up one of those circa-1995 “Under Construction” animated GIF images for the site in the meantime…

Update: Thanks to a tip from Webchick, I got the CCK tables manually reconstructed. All I had to do was rename the tables as per the pattern described. It looks like the 4.7 – 5.x upgrade path for CCK got really complicated, and may have been overlooked. My Drupal 4.7.7 site was fully patched, all modules were up to date, as was core. Upgrading from a fully patched 4.7.7 to 5.2 just plain didn’t work, from the perspective of CCK. Turns out it was a pretty easy fix, but still, a bit annoying. Huge thanks to Webchick for the tip. It’s amazing just how active and helpful the Drupal community is.

My last big issue is wrt embedded Views in several nodes. They appear to be ignoring arguments (but not all of the views are misbehaving, making it a bit harder to diagnose). That’s my task for today, to get the rest of the site behaving properly. Then to fix some layout issues that are unrelated to the Drupal upgrade (the UCalgary theme we had been using was a 4.7 variety, and the 5.0 variety has subtly different css, and lacks our custom stuff).

Drupal Pet Peeve: Loose InputFormat Control

I screwed up in a big way on one of our higher profile Drupal sites. I had configured the default inputformat to include PHP execution, because there are a whole bunch of pages on the site that need to be able to execute PHP, and that was the easiest way to get it done. I was lazy, and didn’t follow best practices. And it resulted in a pretty open security hole, where anyone could create an account and then execute their own PHP (to do stuff like promote their account to Admin, delete the database, send emails, launch ICBMs…). Not cool.

Why was I so sloppy? Basically, I forgot that I’d left user registration open. The site is supposed to be a closed ecosystem, but with user registration enabled, it ain’t.

What I should have done was create a separate “über-inputformat” that included PHP execution, and was only available to admin users on the site. I would then have a separate, more limited inputformat as the default, perhaps with html tag filtering, as well. But here’s where I got lazy – there is no way for me to say “I know that ‘n00b’ is the default format, but I only ever want to use ‘über-inputformat’ so don’t make me choose each and every time I create a node”. Having more than one inputformat available causes the display of a new “input format” control in the node authoring form, and users have to first understand wtf that means, and then they have to figure out why they’d want to choose any of the available options. And if you’re creating a whole bunch of nodes with PHP in them, you have to remember to change each and every one to the “über-inputformat” inputformat, or the code won’t execute. pita.

Which brings me to D’Arcy’s Drupal Pet Peeve #2: Loose inputformat control. You can say which is the default, and then EVERYONE gets to use that. Then, you can add on other additional and optional inputformats, and enable them only for specific roles. But you can’t say that “n00b” is the only available inputformat for anonymous and authenticated users, and that “basic” is the only available inputformat for “members” and that “über-inputformat” is the inputformat to be used by default by admins.

As a corollary to Pet Peeve #2: TinyMCE ignores inputformats. If I have an inputformat configured with PHP execution, TinyMCE is completely happy to try to provide an editor for that, obliviously clobbering the code within the node. You have to go to your account and (temporarily) disable TinyMCE rich text editing before editing any node with PHP in it. It’d be really nice if you could tell TinyMCE to NOT kick in on certain inputformats…

Drupal pet peeve: cron.php

I hate that I have to manually (or scriptedly) call cron.php for every Drupal site I run. Even for multiple Drupal sites on the same server in a multisite configuration. Yes, there are ways to automate it, but eventually they fail. I just manually called cron.php on one of our main sites, after realizing it had silently failed for the last 32 weeks. Hundreds of reminder emails are being sent out now, for events that were held months ago. Yes, there are modules to have cron.php called periodically (poor man’s cron…) but they’re flakey at best, and risky at worst (there is a chance of overlapping cron.php calls if the timing is just right).

Anyway, there endeth the rant. D’Arcy’s Drupal Pet Peeve #1: cron.php

Drupal is the Official UCalgary Podcasting Solution

I was just in a meeting with some folks in our campus IT department, where we were trying to figure out what the official University of Calgary supported podcasting solution would be. We were basically trying to decide if we should jump onto iTunesU in a big way, or roll our own service.

iTunesU is a really strong choice, in that all of the infrastructure bits are handled. No drive space to worry about, no backups to remember. Everything just works.  But, it’s outside of our control, and is rather  strongly Apple-branded. Even though it’s not an exclusive arrangement, and the content can/should be in multiple formats, it’s hard to sell that combo to people who are either

  1. still thinking of locking content within Blackboard (i.e., iTunesU is too open)
  2. wanting to adopt Open Source (i.e., iTunesU isn’t open enough)

Which left us with our second option: roll our own service.

So, over the summer, we’ll be putting together an official campus podcasting solution, hosted using Drupal essentially out of the box (but we’ll eventually add modules like Audio.module, Views, CCK, etc…)

One thing that really impresses me about how our IT folks approach problems is that they don’t react with fear. When we were discussing authentication and restricting access, things that are offered by iTunesU, the response was “we’ll figure that out, and here are some ideas of how we could do that…”

We’ll be, er, inspired by the podcasts.*.edu/.ca websites that are already running. Despite what the press release says, UCalgary is not the first, nor the biggest, podcasting institution…

How to migrate from Drupal 5 to WordPress 2

I migrated my blog from Drupal 5 to WordPress 2 nearly 2 weeks ago. The process wasn’t as painful as I thought it would be, thanks to a handy howto via vrypan.net. Another resource I refer to every time I get into tweaking MySQL rows is UrbanMainframe’s MySQL search and replace tipsheet. Thanks to both of these great resources for helping me through the migration.

This guide is intended only to document what I did. It’s not a polished howto or manual. There is no warranty. If you blow up your database because you didn’t work with offline backup copies, I won’t be able to help you. Actually, if you’re that silly, I won’t be willing to help you, either. Your mileage may vary.

Use a backup copy of your Drupal database, and a fresh WordPress database.

The basic process I followed was:

  1. Work from offline copies of the databases. Dump your Drupal 5 database, import it into a fresh database (say “drupalmigration” or something creative). I did the migration on a separate machine from my “live” server – I used my desktop box, with local copies of MySQL and Apache. Anything with a decent version of MySQL on it will do.
  2. Install WordPress, (you don’t need to install Drupal for this migration) using the same database server containing the copy of your Drupal database (use “wordpress” as the name of the new WordPress database).
  3. Now that you’ve got WordPress and Drupal running on the same database server, in separate databases, run this MySQL script which I modified slightly after the file provided by vrypan.net. The script assumes the WordPress database is called “wordpress” and the Drupal database is called “drupalmigration” – feel free to modify the script to match the database names you need to use, if they differ.
  4. That should do it. Log into your WordPress site. You might have to hand tweak the usernames, but all posts and comments should be there…

One additional thing I had to do was fix the comment_ID values in the wp_comments table. After migration, they were too big for the data type, and things went poopy. I’m sure there’s an elegant way to renumber rows in MySQL. I used brute force, by dumping the table to a .sql file and opening that in a text editor to do a search-and-replace to lower the numbers used as primary keys. I then moved the old table out of the way (renaming it to “wp_comments_old“) and imported the new wp_comments table definition and content. It was a funky thing to have to do, but it solved all kinds of comment-related misbehaviour.

Test things out in the migrated database. If all seems well, go ahead and dump the wordpress database to a .sql file, and import it into a new database on your server. Install and configure WordPress on your server to use this new database. You may need to manually change the URL used by the blog, so that it matches the “live” server rather than whatever you used as a staging/migration server. The values are in the wp_options table, with option_name of “siteurl” and “home” – change those values to whatever matches the root URL for your blog.

You’ll also have to make sure all files are in the proper place, so URL references from the old Drupal content doesn’t point off to 404 error pages. That’s an exercise left to the reader. I just SSHed into my server and used a lot of cp -R drupal/directoryname wordpress/directoryname – being paranoidally careful to copy files rather than just moving them. Always keep backups.

Update: I’ve updated the SQL script to automatically set the comment and category counts, so it should appear to work better now.

Switched back to WordPress

I’ve been using Drupal for my blog for just over a year now, and it’s been a really great platform to work in. I use it pretty much all day for projects at the U of C as well. But it just feels a bit lacking in the area of managing a personal blog, compared with WordPress which is built solely for that purpose.

I’ve been missing things like email subscriptions to comments, and some of the other niceties that WordPress has had nailed for a long time, but are missing in Drupal.

So, if you can read this, it worked. But things are going to be messy for awhile while I finish tweaking stuff. If anyone knows the quick easy SQL to run to recount all comments for posts, to properly set the value of wp_posts.comment_count I’d appreciate it. All comments are properly in place, but they don’t show up in the comment count indicator until/unless someone posts a new comment on the blog entry.

In the meantime, all static pages (including About, Contact, Links, etc…) are borked. I’ll fix them up as I have time.

Update: Lovely. Looks like new comments are being rejected here. wtf. worked fine in staging before moving here… A blog without comments. Good thing I left Drupal…

Update 2: Things are pretty much up and running. I’ve added a bunch of modules, and will start playing when I have/make time. Overall, I’m pretty happy with it. I miss some of the power of Drupal, but am liking the simplicity of WordPress.

Upgraded to Drupal 5

I just finished the first pass at upgrading this blog to Drupal 5.0. Looks like almost everything is working right out of the gate. I hit a few minor glitches:

  1. spam.module has a strange bug, where it fails to display nodes with ID larger than 1519. Node 1520 and higher failed to display at all until I disabled spam.module and switched to Akismet.
  2. CCK – my bikelog is MIA. not the end of the world – actually, I’d hoped to just go ahead and retire it and do what normal/sane people do: get a cyclecomputer. But, enough people find their way to that page from the CCK/Calculated Fields page that I’ll give ‘er a shot when I get a chance.
  3. The K2-derived theme I’d been using borks under D5. Again, not the end of the world. I’ll take a look at upgrading it later. For now, I’m kinda liking the new default Garland theme… Theme updated. Borrowed snippits from Garland to get the scripts etc… properly included.
  4. TinyMCE appears to be shy. It’s installed and enabled, but refuses to show up. Again, not the end of the world, as I’d just as often write raw text/html or use Performancing for Firefox, which works just fine.
    Update: I grabbed FCKEditor, and it’s doing a decent job. I miss having the user setting that let me turn off rich text editing by default, so it doesn’t bork embeded code, but maybe FCKEditor doesn’t do that…. Bork embedded code, I mean.
    I’m really not a fan of FCKEditor’s lack of semantic markup (using br br instead of wrapping paragraphs in p elements, for example) but it works.
  5. The code I’ve been using to automatically generate the colophon (list of active modules, etc…) borks under Drupal 5.

There may be other gotchas. I did the upgrade on my desktop box, then moved it into place so I’m relatively sure nothing is pouring smoke…

I just finished the first pass at upgrading this blog to Drupal 5.0. Looks like almost everything is working right out of the gate. I hit a few minor glitches:

  1. spam.module has a strange bug, where it fails to display nodes with ID larger than 1519. Node 1520 and higher failed to display at all until I disabled spam.module and switched to Akismet.
  2. CCK – my bikelog is MIA. not the end of the world – actually, I’d hoped to just go ahead and retire it and do what normal/sane people do: get a cyclecomputer. But, enough people find their way to that page from the CCK/Calculated Fields page that I’ll give ‘er a shot when I get a chance.
  3. The K2-derived theme I’d been using borks under D5. Again, not the end of the world. I’ll take a look at upgrading it later. For now, I’m kinda liking the new default Garland theme… Theme updated. Borrowed snippits from Garland to get the scripts etc… properly included.
  4. TinyMCE appears to be shy. It’s installed and enabled, but refuses to show up. Again, not the end of the world, as I’d just as often write raw text/html or use Performancing for Firefox, which works just fine.
    Update: I grabbed FCKEditor, and it’s doing a decent job. I miss having the user setting that let me turn off rich text editing by default, so it doesn’t bork embeded code, but maybe FCKEditor doesn’t do that…. Bork embedded code, I mean.
    I’m really not a fan of FCKEditor’s lack of semantic markup (using br br instead of wrapping paragraphs in p elements, for example) but it works.
  5. The code I’ve been using to automatically generate the colophon (list of active modules, etc…) borks under Drupal 5.

There may be other gotchas. I did the upgrade on my desktop box, then moved it into place so I’m relatively sure nothing is pouring smoke…