Tertiary menu block

… or "how I re-invented the wheel". Again

I found myself needing a tertiary menu in Drupal yesterday, which sadly it doesn't provide by default. There is a primary menu and a secondary menu that can auto-populate based on the primary menu selection, but sadly that's the level at which it stops.

Google helped me find a few blogs that show how to easily generate an arbitrary level sub-menu, though most are for D5 and not D6. Ignacio Segura amended code on this blog that makes it all work for D6:

No-fuss Drupal multi-site deployment with symlinks

When creating a Drupal site for clients, many people use a temporary hostname for development purposes. What's more, that hostname is not generally on the same domain as the production site. I'm sure I'm not the only one to use client,mydomain.com to develop the www.client.com site.


When you — like me — use Drupal in a multisite setup, where the same codebase is shared between many sites, you'll have per-site settings, files and images. These are located in a directory structure that's based on the hostname you're accessing the site under. Eg: the files and settings for client.mydomain.com live in the sites/client.mydomain.com/ directory.

However, when the time comes to deploy the site to its production hostname, those settings and files need to live somewhere else. Moving them can result in link and image breakage on the front-end, which is never a good look and means you might need to painstakingly update links and images on all your pages.



Seeing as the Australian governments proposed mandatory internet filter will filter all traffic on port 80, I thought it 

would be helpful to provide a Drupal module that allows you to automagically provide an alternate link to each page on a site.

Your web server should be configured to serve content on a 2nd port, beside port 80, so as to not interfere with browsing requests from users outside of Australia.

fast paging in the real world

Some time ago I attended the "Optimisation by Design" course from Open Query¹. In it, Arjen teaches how writing better queries and schemas can make your database access much faster (and more reliable). One such way of optimising things is by adding appropriate query hints or flags. These hints are magic strings that control how a server executes a query or how it returns results.

An example of such a hint is SQL_CALC_FOUND_ROWS. You use it in a select query with a LIMIT clause. It instructs the server to select a limited numbers of rows, but also to calculate the total number of rows that would have been returned without the limit clause in place. That total number of rows is stored in a session variable, which can be retrieved via SELECT FOUND_ROWS();  That simply reads the variable and clears it on the server, it doesn't actually have to look at any table or index data, so it's very fast.

This is useful when queries are used to generate pages of data where a user can click a specific page number or click previous/next page. In this case you need the total number of rows to determine how many pages you need to generate links for.

The traditional way is to first run a SELECT COUNT(*) query and then select the rows you want, with LIMIT. If you don't use a WHERE clause in your query, this can be pretty fast on MyISAM, as it has a magic variable that contains the number of rows in a table. On InnoDB however, which is my storage engine of choice, there is no such variable and consequently it's not pretty fast.

Userpoints Evaporate 1.0

Well, I finally got a revision 1.0 out the door for one of my Drupal modules.  A fact I thought I'd celebrate with a blog.

The module with this honour is the most recent one I started, userpoints_evaporate, just over a week ago.

I guess it's a nice example of why open source is cool. Someone on the #drupal-support channel on Freenode asked if anyone knew whether an existing module could do what he wanted, which was essentially use the UserPoints module (which works kind of like karma on Launchpad) to automatically expire a set number of points for all users every hour or day (again, kind of like karma on Launchpad).

Simplenews Mass Subscribe

Simplenews is a quick and easy way to set up and manage newsletters on Drupal, but if you add it to a site which already has users, you might want a way to quickly subscribe all your users to your newsletter.

Rather than click through all users and manually subscribe them - which can be a little bit boring if you have thousands of users - you can run a few SQL queries to mass-subscribe everyone in one go.


Since I started doing the occasional consulting job for Open Query, I've seen a lot of MySQL servers that have been installed once and then forgotten about. This gave me the idea to do a short presentation about some basic MySQL server configuration. The first go was at DrupalCampMelbourne and I recently tried (and failed) to cram it into a three minute lightning talk slot at the LUV September meeting.

The title of the talk is (now) MySQL > YourSQL. I chose this not because I think that MySQL is better than the $other_database you use or because I may or may not run a newer version of MySQL on better hardware, but because I use InnoDB and not MyISAM as the default table format. More importantly, I do not run the server with the shipped default configuration.

These configuration tips are also included in the MySQL section of Pro Linux System Administration.

Most distributions ship MySQL with a configuration file that sees you running a server optimised for a system with 32MB of RAM. That was great in 1996, but these days your Nike+ shoes have more capacity than that, so it makes sense to optimise the configuration - or at least to make it not suck quite as badly.

I chose InnoDB as the default storage engine not because it gives me a magic increase in performance or transaction support, but due to the  improved reliability that comes from its ability to automatically recover from crashes better than MyISAM does.

All the following settings go in the [mysqld] section of your my.cnf file.

playing with nginx

Virtually all of my Drupals are hosted on a single server, running Apache with mod_php5. Apache is by no means light-weight, so the server is starting to creak a bit under the combined load of all these sites.

I've been meaning to have a go at configuring nginx with php5 in fastcgi mode, to check the difference this would make on system load.

Simple Drupal Document Management System

Many moons ago I needed a way of storing documents online, so they could be shared between users and easily accessed from many locations.  Thus, Simple Document Management System was born. SDMS is a PHP based front-end to a MySQL database that allows users to upload and download files into and from virtual directories using only a web browser.

Generic Document IconsIt was my second ever PHP project and I wrote it in (bad) php3, with only some informal C coding as experience. Needless to say the code was not great, it used globals and had SQL injection problems. Though I did fix these two particular issues, the code is still old and tired and I've not really maintained it for years.  Bringing it up to date would probably involve more effort than just scrapping it and rewriting it from scratch.

I've been doing a lot of work with Drupal over the past year and I had been vaguely considering reimplementing SDMS as a Drupal module, thus removing the need for me to also maintain code to handle users, passwords, commenting and permissions.

As I got more familiar with some 3rd party Drupal modules, it struck me that it should be completely possible to implement a document management system similar to SDMS in Drupal. Without doing any coding whatsoever. Thus, SDDMS was born.