selective, manual file caching

I’ve disabled WP-Super-Cache on because it was doing quirky things like showing the anonymous front page after someone logged in, etc… And, with our low load and mostly logged in users, it really wasn’t necessary.

Except for the RSS feeds used to generate the Recent Posts and Recent Comments sections on the front page of the site. Without WP-Super-Cache enabled, the front page (and ONLY the front page) took glacial epochs to load, as the RSS feeds were generated, parsed, and embedded. I wanted to be able to cache the feeds, without having to throw the switch on caching the entire site.

Then it hit me – it’s trivial to set up a cron job to curl the feeds to static files periodically, and then I could just use those static files to generate the Recent blocks on the front page. Duh…

So, I modified the crontab on the server to add these two lines:

*/15 * * * * /usr/bin/curl "" > /home/commons/webdata/
*/15 * * * * /usr/bin/curl "" > /home/commons/webdata/

So, every 15 minutes, the sitewide Recent Posts and Recent Comments feeds are updated. I use the static files to generate the display on the front page, using the web-visible URLs for the files at and respectively.

Sometimes, it’s easier to just pull out another tool from the server toolbox, rather than trying to find a way to do it within WordPress all the time…

WordPress Plugin – Post Revision Display

One of the profs using was asking if there was a way to show the “audit trail” for a blog posts. If she’s having students write stuff, and needs it in by a given date (say, an assignment deadline), she’d like a way to know if a post was saved before the deadline, or updated after it. It’s easy for people to futz around with the “published on” date for a post…

So, I did some poking around, looking for plugins or tricks to expose the revision display list without having to send the prof to the blog’s admin UI every time she wanted to look at the info.

I couldn’t find anything, so I asked a question on the WordPress support forum. On a tip from Otto42, I poked around with the wp_list_post_revisions() function. Looks exactly like what I need. So it was pretty simple to write a basic plugin that adds a Filter such that the list gets generated and appended to every post displayed on a blog that uses the plugin. If you’re logged in, and have proper privileges, you’ll also get a link to view the revisions directly. If not, you just get to see that the revisions exist.

I had to copy the wp_list_post_revisions() function and modify it a bit in the plugin, so it behaved as needed. Nothing too major, but the WordPress function relies on echo to dump the list directly, and I needed to modify it to return a string to append to the blog post. Easy peasy.

And so, post-revision-display is born. Install and activate it on your blog, and your posts will automagically generate and display the list of revisions as an audit trail, with no futzing about with themes and hardcoding stuff. Here’s what the audit trail looks like:

Download the plugin here (for now – I’m trying to get it added to…)

UCalgaryBlogs update

The publishing platform has really only been active for the last month, with real faculty and students using it. In that month, it’s already seen more activity, in terms of blog posts written, than has seen in over 3.5 years of activity.

1600 posts.

In one month.

30 days.

And it really hasn’t been launched very publicly on campus yet. I can’t wait to see what people do with this stuff…

I’ve got a pretty strong feeling that people are taking to the WordPress Multiuser platform in ways that they never did with Drupal. That’s definitely not a shot at Drupal – just a statement of how the power of an individual-focused publishing platform resonates with individuals.

why I’m so proud of

I wasn’t convinced that we needed a “campus blogging platform” here at UCalgary. I’d tried to set up one before, at , and watched it basically wither on the vine for 3 years. Little activity, except in small bursts when used in a class. Almost no individual involvement or ownership. Not interesting or relevant to anyone.

I’d decided that a “campus blogging platform” was the wrong tack. Why not just send people to other services that provide the software, for free. Services like or or or etc… They all provide the functionality, hosting, and support, without any intervention by a “campus”.

And then, in conversations with people whom I deeply respect, it was pointed out that there are, in fact, good reasons for having the publishing platform managed by the University.

  • community – if everyone has access to the same tool(s) they can build on each other’s work more easily
  • support – again, if people are using a common set of tool(s) it’s much easier and more effective for us to provide support and strategies for integrating those tools into the activities of teaching and learning
  • ownership – if the platform is hosted by the University, we can guarantee that no corporate entity is going to take it over and change the rules of the game. The license can’t change. The fees can’t go up. Ads can’t find their way onto the blogs…
  • safety – this one is twofold –
    • we need to be able to provide private blogs, where students and faculty can publish content to be seen only to a given audience. This is harder (if not impossible) on services hosted by other organizations.
    • non-US servers. This sounds odd, but if we’re going to be compelling our students to publish anything, we can’t force them to use services hosted in the States, due to implications of DMCA and Patriot Acts. We need to provide a service that’s hosted in Canada, and since there really isn’t a big blogging service hosted up here, we need to host our own on campus.

So, taking those into consideration, it became obvious that we needed a great blogging platform to be available on campus. And that wasn’t it. Following in the footsteps of several others, I grabbed a copy of WordPress Multiuser, and installed it on our IT-hosted virtual machine server. I registered – I wanted to use a non domain name to avoid issues relating to “quality” of content, as well as “branding” of the website. People need to be able to write anything, and not have the constraints of having to live within the official UCalgary design template.

We set up DNS wildcarding, so people could have their own blog subdomains such as and installed the Domains plugin so people could also use the service for their own custom domains.

And then, I slowly started telling people about it. I didn’t expect much to happen, as it was a stealth project. But, pretty much every person that got their hands on it said it was exactly what they needed. They wanted their students to be free to publish, in their own spaces, without the limitations of Blackboard’s discussion board.

Faculty appeared to be getting on board, and judging from the activity, students were getting into it as well – at least they weren’t rebelling too loudly.

For a portion of Friday afternoon last week, students published 76 blog posts within one hour. We’ve now got 127 users in the system, publishing to 79 blogs (73 of which are public).

That doesn’t sound like much, but for a stealth project with no budget, we’ve been able to help over 100 people publish content, with over 1000 blog posts published so far, since the service started getting use in September. That ain’t half bad 🙂

Batch adding users to a WordPress site

I’m working with a faculty member who is using a WordPress with his students this semester as a place for them to publish and reflect as a group. To make things easier for everyone involved, it’s a good idea to batch create user accounts for the students so they don’t have to go through that process (it’s easy, but every step avoided means people are more comfortable and less aggravated with a service).

Do support that batch creation of users, I installed the “Import Users Plugin” which, surprisingly, provides a way to import users into a site. All you need to provide is a username and email address for each student and it will create the account, generate a password, assign the specified user Role, and send an email to the student so they can login. It doesn’t create blogs for each student, but for our current use-case, it’s ideal – adding users to a single blog in a WordPress Multiuser service.

If you need to batch create a bunch of users, first enable the “Dagon Design Import Users” plugin on your blog, then follow these instructions:

The list of users could be pulled from Blackboard or Peoplesoft, but needs to be reformatted into

username|email address

structure so the plugin can make use of it.

learning communities

I spammed over 2200 faculty members with an invitation to vote on topics of interest for formation of Learning Communities, and used the opportunity to sneak in the first public mention of There’s no turning back now. Full steam ahead!

The votes have already started to roll in on the poll, and soon we’ll have a pretty good idea of where to take the project. w00t!

upgraded to wpmu 2.6.1

Donncha pushed the WPMU 2.6.1 update live today, and it’s a required upgrade for security reasons. I just wanted to post that I’ve upgraded to WPMU 2.6.1 and everything appears fine. It took all of 2 minutes to do, too.

Here’s my process:

  1. back stuff up.
  2. login to the server via ssh
  3. download WPMU 2.6.1 into ~/temp, and unzip it.
    cd ~/temp
  4. delete the wp-content directory in the freshly downloaded copy of WPMU 2.6.1 – I do this so I don’t accidentally overwrite any customized themes, or nuke anything in mu-plugins or plugins…
    rm -R wordpress-mu-2.6.1/wp-content
  5. copy the fresh copy of WPMU over top of the existing one in the web directory
    cp -R wordpress-mu-2.6.1/* ~/webdata/
  6. run the WPMU upgrade site script to run any necessary updates (I don’t think there were any database updates, but it’s probably a good idea to run it anyway). This will automatically run the script on each blog installed on that copy of WPMU.
  7. done. test some blogs to make sure stuff is working fine.

User Avatar Photos in WordPress

WordPress has supported Gravatars for awhile, which is great, but if you’re rolling out a site for a bunch of students to hammer on, it’s not ideal to have to send them to a third party service to set up photos. It’s awkward, and confusing, for new users to have to go somewhere else to add a photo to their profile. And profile photos can be very useful, especially at the beginning of a semester when everyone is just getting to know everyone else in a class, to put a face to a name.

So, for, I just installed the handy User Photo plugin. Now, any site can enable this, and the users of that site will be able to add photos to their profiles, like this:

The plugin can be configured with custom sizes for the full-size and thumb versions of the avatar, and the avatar image can be deleted and/or replaced at any time.

It’s not completely trivial to enable – because the themes need to be User Photo aware. That’s pretty easy to add, though. For the cutline theme we’re using on a project, I edited a handful of files to add the code, and it works great. On index.php, and single.php, just add this wherever you want the blog author’s photo to be displayed on the post (I put it in the section displaying the post meta information):

<?php if (function_exists('userphoto_the_author_thumbnail')) {  userphoto_the_author_thumbnail();}?>

Wrapping the thumbnail display code in a function_exists conditional means it will degrade nicely if the plugin is unavailable. Always a good thing to degrade instead of borking.

That results in this display when viewing the post:

Now, if you also want to show avatars on the comments, just edit comments.php to add this code (I put it in the comment meta info section):

<?php if (function_exists('userphoto_comment_author_thumbnail')) { userphoto_comment_author_thumbnail();}?>

And that will look like this when displayed on the blog:

If a user hasn’t added an avatar, it won’t display any image. But if they do have one, they’ll get the properly sized version of their avatar image displayed automatically. Easy peasy. It’s a bit awkward having to edit the themes, but it’s not difficult. The hard part will be remembering to re-apply the edits if the themes get updated (hence this post…)

WPMU Tweakage for – Part 1

I said I’d share what I’ve done in setting up, and instead of waiting for The Mother of All Blog Posts, I’m going to break it up into a few parts. In Part 1, I’ll talk about some of the mu-plugins I added. Some are really cool, some are just shiny…

Basically, start with a fresh copy of WordPress Multiuser. I’m running 2.6 on Then, add the following bits into the wp-content/mu-plugins directory.


A great plugin that provides an extra tag to embed on pages to list all blogs in a WPMU installation. Good for a blog service directory..


Adds a bar to the top of every page of every blog, similar to, to make it easy to manage a site and log into the service.

WordPress MU Sitewide Tags Pages

Donncha’s awesome plugin to essentially aggregate every blog into a single überblog so archives and tag clouds can be shared. At first, I thought this was a silly way to do it – Drupal could have easily just displayed tag clouds and archives with no pre-aggregation, but it works, and it works very well.

Sitewide Feed

Generates combined feeds for all posts, comments, and pages posted to the WPMU service. Makes it easy to keep up to date on all activity. I’m guessing/hoping this will become essentially useless once the service takes off – I can’t imagine following hundreds of blogs/comments once they become active…

I’ve got a few more miscellaneous mu-plugins installed, but I may be yanking them as they’re really not critical and I want to keep the amount of loaded code down…

Next up: Part 2 – the “main” theme (including home page, sidebar, archives, tag cloud, etc…)

Pimping the WPMU for

I’ve been slowly tweaking the WPMU install that drives – it’s not quite ready for prime time, but it’s darned close.

It’s now got:

  • multiple blogs per user, and multiple users per blog
  • subdomain hosting for each blog (i.e.,
  • domain mapping – want to use your own custom domain? want to point to the blog you’ve got at there’s a setting for that, and then you just have to tell me what domain you want me to tell the webserver to respond to.
  • multilingual admin interface. English. French. Spanish. Chinese. Klingon. Well, I still haven’t found the Klingon.po file for WordPress, but once I do… *shakesfist*
  • over 100 themes, most of which are customizable. Want a photoblog? Got it covered. Newsletter? Done. Research project? Sure thing.
  • 500MB of upload space quota per user. This could be increased if needed.
  • Sitewide tag cloud and archives – want to find out who else is writing about mitochondrial RNA? Just hit the tag…
  • Blog directory listing all blogs in the system (currently, some test blogs, and the UC Dinos Football Blog! WOOHOO!)
  • A handy-dandy blog manager bar at the top of all pages – if you’re logged in, it gives you easy access to anything you want to do. If  you’re not logged in, it gives you an easy place to login from, from any page on the service.
  • Lots of other great WordPress goodies, like podcast serving, editing from your iPhone or iPod Touch, great visual editor for posts (with spel chekker, too!) and collaborative blogs with multiple authors.

But, there are still a few things on my todo list before I consider it fully ready for prime time:

  • Documentation. It helps if there’s some M to RTF. I’ll be linking and borrowing heavily from the great stuff already out there…
  • A UCalgary theme (or themes) for sites that need to look all offishul ‘n junk.
  • better antispam – I can’t use Akismet because I have a budget of $0.00, and SpamKarma2 is EOL. Maybe Mollom? It doesn’t play well with WPMU yet…
  • hmm… actually, that’s pretty much it. once it goes live, it can be tweaked on the fly…

Once it’s been live for a bit, I’ll look at stuff like BuddyPress, integration with Flickr, integration with MediaWiki, and a bunch of other stuff. So far, it’s been fun setting up the service. Now to start rolling this sucker out…