Apr 07 2009
Apr 07

Drupal For NGOs has been away for a while but will restart again later this month as a regular bi-monthly event. The aim is to empower NGOs to implement and manage their websites by knowing what modules are available and how to use them. Each event will cover a topic in detail, showcase recent projects, and feature a Drupal question and answer session.

Which topic is covered at each event will be decided by a poll, so if there's something you'd like to know more about please cast your vote or make a suggestion.

This month we will be talking about Sub Sites (Organic Groups).

If you have any experience with Organic Groups that you'd like to share please get in contact.

Sun Microsystems is hosting this month's Drupal For NGOs, and will also be providing presentations on Scaling And Optimising MySQL and Backing Up MySQL Data.

We will also be giving away two Drupal books that Packt Publishing have generously contributed:

  • Drupal 6 Site Builder Solutions
  • Building Powerful And Robust Websites With Drupal 6

Get A Ticket

The event is free, but you will need to RSVP if you would like to attend. Full event details are on the registration page.

Future Events

Rob Purdie did an excellent job of starting Drupal For NGOs and keeping it going last year. He's now moved to New York, but hopefully can take part via a live connection. Rob has passed on responsibility for organising the event to Robert Castelo, and if you'd like to host Drupal For NGOs or have any other suggestions please contact Robert.

The next Drupal For NGOs will be  in June at Amnesty International and we will be discussing using Drupal to create Intranets.

If we have the technology we will try to make these events accessable via the web.


The event will be limited to 100 attendees. If it fills up before you get a ticket, please get in contact to let us know we need to get a bigger venue for the next event. Also note that there is a pub below the venue, where the meeting will likely move afterwards.

The tag for this event is drupal4ngos200904, and all presentations will be available after the event.

Apr 06 2009
Apr 06

This past weekend I was in Ireland for DrupalCamp Galway. The organizers pulled off a great camp and they deserve a ton of kudos for getting things started, keeping things smooth, and pulling off a really fun event. Stephane Corlosquet (scor), Stella Power (stella), Heather James (heather), and Alan Burke (alanburke) did some really great things for this camp. Aside from a great venue with several rooms, at DERI, and a good lineup of great Drupal info, they also ran a site-building challenge to build websites for two charities in Ireland. They also provided space for an all-day documentation sprint. Then there were the little extras that make events more betterer, like having lots of tea, coffee and cookies (yeah, I know, OK, "biscuits") and arranging reservations for group dinners in the evenings where we could all chat more and get to know each other. Whew.

Over 60 people showed up and many of them were newbies. They got the big room to explore Drupal from the ground up and the more advanced folks moved down the hall to do more talkin' shop. The newbie room was led off by someone who is fairly new to Drupal himself, Leon Butler (star_nixon). He has just recently built a site with no coding and just some HTML knowledge. He walked folks around the site to show the things he could do and give people a feel for a Drupal site. That was followed on by presentations that gave an overview of Drupal, installing it, and building a live site (for the third charity, Shadowbox).

In the advanced room, we had a ton of topics. We ended up covering things like testing, security, Drupal 7 changes, and work on semantic web. I hopped up to talk about usability, both in Drupal 7 and how to approach looking at usability issues on a per site/per client basis. Later in the day I did two different presentations on documentation. They used the same slides but I was talking to very different groups, one in the starter room and the other in the advanced. My main emphasis for the newbies was that everyone can help and that being new to Drupal is an asset when it comes to documentation, not a hindrance. For the mainly dev room, I focused more on the "non-writing" ways to help documentation. The basic idea was to let people see that there are lots of things that can be done, many benefits (other than just warm fuzzies) and that they could all get started the following day at the doc sprint. ;-)

While most people attending on Sunday took part in the challenge of building the charity sites, we had a small core group of folks hanging out in the documentation room with several people popping in throughout the day to touch base and see where they could help out. We had an ideal group, in that everyone there was new to Drupal, so they tackled a walk through the Getting Started handbook and the Drupal Cookbook, taking notes about confusion or annoyances, editing the pages to fix grammar or add clarity, and having discussions about a newbie's take on the experience of it all. It was a ton of great feedback and I hope to see them all around the Drupal project even more because they are already awesome contributors. I also hope that maybe there will be a few informal doc sprints around Ireland. ;-)

Sunday wrapped up with choosing a challenge winner and awarding prizes. I was asked to be one of five judges, along with Stephane, Diliny Corlosquet, John Breslin and Ronan Joyce. It was a really hard decision because basically both sites were awesome and both charities were ecstatic with the result. In the end when we tallied up the judges' votes it was only a 2-point difference out of 100, for the Zikomo site. Both teams got prizes though and it really felt like a great day for everyone. Win, win, win all around. Thank you Ireland Drupalers, what a blast!

Apr 06 2009
Apr 06

Today I had the task of checking out Drupal core and a load of modules for a new site, but all those CVS commands made me think there must be an easier way. So I started looking into scripting the process. This is when I came across Patrick Corbett's blog post "Drupal CVS Checkout Shortcuts".

(This is all done on Mac OS X Leopard) I started by opening up terminal and running the command "vi ~/.profile" this opened up the vi text editor and created the file .profile in my home directory. I copied the code from Patrick's blog post, saved, closed and reopened terminal and ran "getmod cck" to test it worked. To my amazement it worked.

Now came the time to change the script to make it do what I wanted. I wanted to be able to specify a module version, and checkout Drupal core. So I set out to find the right commands and write up the functions. Below you will see my code. I added a version variable to getmod() and I added getdrupal() and updatedrupal() functions to take care of core checkouts.

One issue I came across was that I wanted Drupal core to checkout into the current directory rather than the default "drupal" directory, but the problem was I didn't know what the current directory would be. Thanks to @bobthecow for the idea of using the pwd command. I was able to set the current directory to a $FOLDER variable, cd back one directory then checkout Drupal core into the previous directory using the value stored in $FOLDER.

To summerise. Copy the code below into a file called ".profile" in your home directory. Then restart terminal. Use the following commands.




function getmod () {
cvs -z6 -d:pserver:anonymous:[email protected]:/cvs/drupal-contrib co -r DRUPAL-6--$VERSION -d ./$MODULE contributions/modules/$MODULE;
getrevs $MODULE.module
function getrevs() {
cvs log "${1}" | egrep 'DRUPAL-.*:' | sort
function updatemod(){
cvs update -r DRUPAL-6--"${1}" -dP
function getdrupal(){
cd ..;
cvs -z6 -d:pserver:anonymous:[email protected]:/cvs/drupal checkout -d $FOLDER -r DRUPAL-"${1}" drupal;
function updatedrupal(){
cvs update -r DRUPAL-"${1}" -dP

Drupal CVS bash script

Apr 05 2009
Apr 05

A brief history to begin with ...

What's pivots_block?

The idea is to generate "related modules" recommendation based on co-citations. Suppose we have TinyMCE and FCKeditor co-mentioned together in many forum discussions, then we consider the 2 modules related to some extend. Here is a detailed explanation.

Where we are now?

With the help of d.o. infrastructure/webmaster team, we deployed pivots_block on d.o. Google Analytics reports showed that pivots_block invited 3 times higher click-throughs than the simple "New forum posts" block. Also, we found that the classical correlation coefficient algorithm received more click-throughs than the other 3 extended algorithms. In general, we think pivots_block works pretty fine for the d.o. community.

The roadmap to the future ...

The next major improvement

One key factor to pivots_block is to correctly detect module citations in forum discussions. Currently we used 1) the popular aliases such as CCK and 2) the module title names together with the keyword 'module' as detectors to match module citations in discussions. This might have missed quite a few module citations.

To fix that, we recruited a graduate student at University of Michigan and manually read through all 12,742 messages posted to d.o. forum in November 2008. By that we hope to collect a list of module aliases used by the community, and then use that to improve accuracy of detecting module mentions. The work is almost done, and we hope to apply it soon to d.o. and test if it improves the recommendation quality.

Other alternatives

One alternative is to generate module recommendations based on , which is current running on d.o. Its limitation, however, is that it tends to recommend complement modules than substitute modules, because people rarely use substitute modules in the same sites. Google Analytics showed that this algorithm had slighted lower click-through rates than the original co-citation algorithm, but not statistically significant.

Another alternative is to use ApacheSolr MoreLikeThis. This is promising because d.o. search is running on ApacheSolr already. However, to my knowledge (maybe limited), the relevancy matching algorithm of MoreLikeThis is text-based. That is, modules are related because their project text descriptions are similar. This might or might not work well for d.o. modules. But it's definitely a direction to explore.

The last alternative is to generate related modules based on module ratings such as http://drupalmodules.com/. This is a promising idea too. One concern is that it might be subjective to deliberative manipulation, indicated by some research literature. Besides, this approach is only possible after implementing a module voting system in d.o. redesign.

Action plan

First, I'd like to apply the next (probably last) major improvement of pivots_block to d.o., as described earlier, and measure its click-through rate. That would be the best we can get from the co-citation pivots algorithm.

Second, I'd like to work with the ApacheSolr team and see if we can use ApacheSolr MoreLikeThis to make "related modules" recommendations on d.o.

If ApacheSolr MoreLikeThis receives higher click-throughs, which would indicate that it's more helpful to the community, then it's better to keep MoreLikeThis. And vice versa. If we decide to keep pivots_block, my future plan then is to make it a more general-purpose module and build it on top of ApacheSolr (details will be announced later).

I'll try to finish this research in April and report it back to the community. Drupal ROCKS and hope we'll make d.o. module recommendations work better!!

Apr 04 2009
Apr 04

I visited my site a couple of weeks ago and discovered a pile of comment spam. That's not unusual, of course; what *was* strange was that Drupal's Comment Notify module hadn't told me about them. Some poking around revealed that, lo and behold, the site wasn't sending any email. The problem's nature meant I had gotten no notification: It was the silent site-killer.

So first off, I want to apologize to anyone who's tried to contact me thorugh tomgeller.com or gellerguides.com and not gotten a response. Simply put, I never got your message: If you remember your query, please send it again. The fault was entirely mine, because I hadn't instituted a simple procedure that would have prevented the problem. To wit: I should have tested the site periodically.

And so should you.

In fact, here are five areas every Web admin should test regularly:

  1. Anonymous user experience. Log out, then test your site's appearance and function. One mis-set permission can stop visitors in their tracks.
  2. Sign-up experience. The sign-up email is your users' first personalized encounter with your site. Are you sure it represents your current message? And do the sign-up screens lead logically from one to the next?
  3. Links and scripts. File paths sometimes change during system updates, but you'll never know until you try to access a link or script... and have it fail. Discover the problems before your users do!
  4. Images. Ever had your images disappear after an upgrade? There are two common causes: putting image files in the wrong place (such as /files), and forgetting that you'd modified pieces of a theme when you upgrade it. Which leads us to our last test...
  5. Backup and restore. "You're only as good as your latest backup", they say. Further, "Your backup is only as good as your ability to restore from it". Whether a backup is missing or unusable doesn't matter: The result is the same.

I'm sure this isn't a complete list, and fear the next time my site dies a silent death. So help me out: What other areas do you think site admins should test regularly?

Apr 02 2009
Apr 02

Play Video

Movie link (right-click to download) Problem with this video? Contact me

The definition of a workflow, according to Wikipedia, is a "depiction of a sequence of operations". When taken at face value, a workflow is typically something you want to automate in Drupal. In other words, what we're talking about is Drupal Automation and my guess is, you'll want to automate things in Drupal based on certain events.

The confusing part of Drupal automation is the fact that you need to know what works together to accomplish such automation. With the modules of Workflow, Actions*, Triggers* (* Part of Drupal 6 core) and Rules, it can be quite confusing when it comes to automation.

Put simply, in Drupal 6, you can still use the Workflow module (which I don't show in the video) but you can also get by with the default Triggers and Actions (as mentioned, already installed with Drupal). However, unless you know you need to install Workflow module to achieve the automation you're seeking, and potentially install Triggerunlock module (which you don't really need if you install Workflow in Drupal 6), things can get really confusing, really fast.

So, aside from trying to confuse you with the above paragraph (I did that on purpose), about all the setup and things you do or don't need, I focused a bit more on the Rules module because it's a one-stop-shop for automation which goes beyond what you can do with Triggers, Actions and Workflow.

Even though I'm a convert to Drupal's Rules module, my compliments go out to John VanDyk (whose book helped me learn Drupal even better) for creating Workflow and Actions (which I started with in Drupal 4.7) and to Wolfgang Ziegler for creating the ever powerful Rules module. I can only hope this video will provide you with most everything you need to know to automate things so you can achieve your ultimate Drupal workflow!

Note: If you're still working with Drupal 5, then Workflow, Actions, and Workflow-Ng (also by Wolfgang) will give you the automation you need. In most all cases, you'll definitely want Token module installed so you can do the cool stuff the big boys do.

Apr 02 2009
Apr 02

There has been a lot of excitement the last few weeks since I gave my presentation at Drupalcon in Washington DC. Where I spoke about how the usability team of Drupal has been working on changing the workflow in issues queue, allowing user experience people to review interface changes to Drupal and how the larger design process conflicts with our current process.

One of the things I noticed during my review of this presentation, that the title doesn't really reflect it contents. So in the upcoming week I will spend time, on writing about my thoughts about Drupal's future releases.

We are having a lot of conversations with Mark Boulton and Leisa Reichelt, who are working on Drupal 7's user experience . As the weeks progress, we need to make sure that we don't just work hard on getting involved with all of their work but also fix all of the low-hanging fruit (issues) that has been found at the usability test in Baltimore.


Apr 01 2009
Apr 01

Developers are all familiar with the default behavior of the drupal menu systems "local tasks" (aka tabs). These appear throughout most Drupal sites, primarily in the administration area, but also on other pages like the user profile.

Generally, developers are pretty good about creating logical local tasks, meaning only those menu items which logically live under another menu item (like view, edit, revisions, workflow, etc... live under the node/% menu item).

But sometimes, these tabs either don't really make sense as tabs or you simply want to have the flexibility of working with the items as "normal menu items", or those menu items which appear under admin/build/menu.

I recently wanted to move some of the tabs on the user profile page (user/UID) into the main menu so that I could include them as blocks.

For some reason, developers think the user profile page is a great place to put tabs for user related pages such as friendslist, tracker, bookmarks, notifications and so on. But these types of items are less a part of the user's account information than they are resources for specific users. Personally, I would not think to look at my account information on a site to find stuff like favorites or buddies. I'd expect those items to be presented somewhere much more obvious like a navigation block.

Initially, this may seem like a trivial task. My first thought was to simply use hook_menu_alter() and change the 'type' value of the menu item from MENU_LOCAL_TASK to MENU_NORMAL_ITEM. However, for reasons I don't understand well enough to explain in detail, this does not work.

In order to achieve the desired result, you must change the path of the menu item and incorporate the '%user_uid_optional' argument, replacing the default '%user' argument.

All very confusing, I know. Let's look at an example.

The notifications module (which provides notification on changes to subscribed to content) uses the user profile page rather heavily. I don't want its links there, I want them in the sidebar where users can always see them.

* Implementation of hook_menu_alter().
function MODULENAME_menu_alter(&amp;$callbacks) {
$callbacks['notifications/%user_uid_optional'] = $callbacks['user/%user/notifications'];
$callbacks['notifications/%user_uid_optional']['type'] = MENU_NORMAL_ITEM;

So I have moved the notifications menu into my own menu, changed the type, used %user_uid_optional instead of %user, and unset the original menu item.

This works fine except for the fact that you'll lose all of the other menu items under user/%user/notifications! You need to account for all menu items in the hierarchy to properly reproduce the tabs in the main menu system, so we add the following:

['notifications/%user_uid_optional/thread'] = $callbacks['user/%user/notifications/thread'];
$callbacks['user/%user/notifications/thread']); $callbacks['notifications/%user_uid_optional/nodetype'] = $callbacks['user/%user/notifications/nodetype'];
$callbacks['user/%user/notifications/nodetype']); $callbacks['notifications/%user_uid_optional/author'] = $callbacks['user/%user/notifications/author'];

And of course, we don't want this code executing at all if our module is not enabled, so you'd want to wrap the whole thing in:

if (module_exists('notifications')) {



Keep in mind that not all modules implement menu items using hook_menu(). It's becoming more and more common for developers to rely on the views module to generate menu items, and this is a wise choice. Menus generated using views (ala bookmark module) can be modified to get the desired result without any custom code.

Apr 01 2009
Apr 01

If you have some friends with a Last.FM account, head over to http://perfectfestival.com, where you can generate the homepage for a fictive music festival where all their favorite bands are playing! Try something like "Hey chx, I'm going to Perfect Festival at the end of June, should I get you some tickets too?"

The idea came up two days ago when I was playing with the Last.FM API and Wordle. The website is still a little rough around the edges, but considering we only spent a couple hours on it I'm pretty happy with the results. Thanks to Troy Shields for jumping on this fun project with me and creating the design.

I'm simply pulling the user's top 50 artists from Last.FM data, sorting them by overall listener count for more credibility (that obscure band that you really like would never be on the main stage, with Coldplay opening for them...). The pictures are also from Last.FM, I decided to use their resized version rather than try to download the files and manipulate them with imagecache.

One common issue is that people listen to bands that don't play concerts anymore. The following three lines of code take care of 90% of the cases:

if ($artist['name'] == 'The Beatles') {

Apr 01 2009
Apr 01

Early this morning, just past midnight my time, I put out 1.0 releases of Advanced Forum, Advanced Profile Kit, and Author Pane in both D5 and D6 with the exception of APK D6 which still needs a lot of work. I was trying for a 4/1 release just for fun but they're showing up as 3/31 for me (though one person reported it says 4/1 for them). If you've been using the RCs, there's not much change. I've waited until the bug reports stopped on the RCs before doing the release and I haven't made major changes for a while. If you're one of those folks the usage stats reports on the early alphas, I'm afraid it's going to be a rough upgrade.

These releases were a long time coming. Advanced Forum started out as a modified Flatforum on Coulee Region Online two years ago and has been a module of its own since November of 2007. Advanced Profile Kit started out as a tutorial based on the profiles on Coulee Region Online and has been a module since January of 2008. Author Pane is the new kid on the block but is actually bits of AF & APK pulled out so they could be shared. I've been working on these fairly constantly all that time, slowly adding features and working out the bugs. There is still much work to do on Advanced Forum but it has gathered so many users I felt it was time to make a cutoff point so they would have a solid release.

Which brings us to the future. The D5 line is done as I am leaving D5 behind on all my sites and don't care to work with it anymore. I will continue to support it and provide bug fixes until D7 is released but it's definitely on maintenance only mode for me. D6, however, still has much work to do. Advanced Forum will be getting a 2.x branch soon to file feature requests against and I will start in on them in a month or two (I need a short break). For Advanced Profile Kit, I plan on making the move to Panels 3 and finishing up a more limited feature set to give it a 1.0 release. Then that, too, will get a 2.x branch to start in on some of the plans I have to make it live up to the "advanced" in its name.

So this isn't an end to the long journey but merely a milestone. I'm excited to continue taking Drupal's forums and profiles to the next level and hope you all will keep on the journey with me to make these modules the best they can be.

Thank you all for your continued support. Without users, these modules would not be where they are today.


Apr 01 2009
Apr 01

Apr 1, 2009

If you have some friends with a Last.FM account, head over to http://perfectfestival.com, where you can generate the homepage for a fictive music festival where all their favorite bands are playing! Try something like "Hey chx, I'm going to Perfect Festival at the end of June, should I get you some tickets too?"

The idea came up two days ago when I was playing with the Last.FM API and Wordle. The website is still a little rough around the edges, but considering we only spent a couple hours on it I'm pretty happy with the results. Thanks to Troy Shields for jumping on this fun project with me and creating the design.

I'm simply pulling the user's top 50 artists from Last.FM data, sorting them by overall listener count for more credibility (that obscure band that you really like would never be on the main stage, with Coldplay opening for them…). The pictures are also from Last.FM, I decided to use their resized version rather than try to download the files and manipulate them with imagecache.

One common issue is that people listen to bands that don't play concerts anymore. The following three lines of code take care of 90% of the cases:

<?php if ($artist['name'] == 'The Beatles') { continue; } ?>

Apr 01 2009
Apr 01

I've recently begun a project to create a drupal install capable of handling multiple domain names with independent front ends and themes for each site and a shared code and database. This project will be tailored to the online marketing needs of the modern service professional and will allow each to post company information, profiles, portfolios, service lists, products for sale, as well as integrate into their twitter, facebook and craigslist accounts for social media appeal.


I've been able to put quite a bit of it together with a coterie of modules and validators based on Drupal 6. These include Domain, CCK, Views2, Views Attach, and some associated helper modules.

Remaining work

A few areas remain to be developed before i can let anyone use it for anything other than experimenting. Ill try to clean these up tomorrow so i can solicit some feedback. Those include:

  • A way to keep users from logging into each others site with permissions beyond that of a normal user.
  • User profiles as real user profiles, with a contact option
  • Create a "company" node when you add a domain.
    • Display this nodes fields as dynamic menu items on appropriate pages (Contact, About, Home
    • Let site administrators edit this node
    • Include data: email, phone, fax, address, description
  • A dynamic menu that senses the completeness of the domain node items as well as the existence of products or services and adds/removes primary links as desired.
Mar 31 2009
Mar 31

We've been kicking butt with the doc challenges so far this year. Lots of work is getting done to clean up our handbooks. I really want to thank everyone who is chipping in, even if only for five minutes. Every little bit that we do makes it just that much better for everyone. This month's challenge will be an extension of a particular piece of March's style guide challenge; marking pages with correct vocabulary terms. One of the goals for the future of the documentation in the Drupal.org redesign is to use vocabulary terms to help people find what they need, rather than the only way to find something being to know the magic path through the book structure. To that end, we need to actually tag the pages.

We have several vocabularies for handbook pages, some of them just recently added during Drupalcon DC, to help us slice and dice. We have the following vocabularies to sort things out: Audience type, Audience experience level, Drupal version and Page status. When the terms are applied to a page, it will add the term in the corner of the page. Clicking on those term links currently takes you to a pretty ugly unordered list of all the pages with that term. Not horribly useful right now, but those terms on going to be great once we start using them to produce views of content and as a tool to help search for the info you need. With this bright future before us, we'd like to get as many pages as we can tagged up. There is an explanation of the various vocabularies we are currently using on handbook pages in the Style guide's structure page. All you need to do is browse through the documentation, see a page without tags, click the edit tab and add them.

You'll also notice that one of the kinds of terms we are using is for the page status. This tells us if there is work that needs done for the page. If you're looking for a break from tagging the pages, you can always check out the list of pages that need some love to find something to dig into. There is a list of links for the three main "needs work" tags on the Documentation maintenance tasks page, at the bottom, under "Review pages by status." We hope to make this list more useful down the road as well, but even now it is a great help to know which pages need some attention out of all those many pages we have.

This month I will be bouncing around the world quite a bit, so making a regular time for me to be on IRC may be tough. I'll try my best to be on IRC (Freenode #drupal-docs), working on page tagging for an hour each week on Wednesdays from noon to 1 p.m. EDT (16:00 GMT). If anyone would like to set up another regular time to meet with your fellow book hackers, let me know and I'll make sure it gets announced.

Mar 31 2009
Mar 31

From many sides I hear that Drupal sites and themes are ugly, which is partly true, but I took a closer look at Drupal.org themes and handpicked 25 best designed Drupal 6 themes, to prove that Drupal can be beautiful even using standard themes that you can find on drupal.org website. In this post I provided a link to every theme's project page on drupal.org, download link and live demo link. Please note, that download links link to current theme release, which can change in the future, so use project page link (theme title in this post) in the future and download themes from there to keep them up to date.


  • Supports site name, slogan, title, search box, shortcut icon, and primary links.
  • CSS based, tableless design, fixed width layout with 2 columns.
  • Quick edit and delete links, custom search form design.


Acquia Marina

  • 1, 2, or 3 column layout, 15 collapsible block regions
  • Drop-down primary links menu (optional) advanced theme settings to customize without coding!
  • Includes icons, high attention to detail on things like forms, lists, comments, quotes, and Drupal maintenance page

Acquia Slate

  • 1, 2 (either sidebar), or 3 column layout, 14 collapsible block regions
  • Custom front page layout with block/menu overlay and photo
  • Additional block regions on inner content pages, advanced theme settings to customize without coding!


  • Rounded Glassy corners of container.
  • CSS based design without tables, 6 Block regions
  • Pre-Made Search block, attractive comment section.


  • Supports site name, slogan, mission, comment user pictures, search box, shortcut icon, and primary and secondary links.
  • Fixed width layout with 2 columns, 5 block regions available (including content area).
  • Custom search form design, maintenance/site off-line theme, CSS based, tableless design


  • Smart 1-2-3 columns, big amount of regions
  • Fixed width (from 1024px and greater), tableless (css based)
  • XHTML Transitional valid, Tested in firefox 2+ / opera9.x / chrome / ie6+


Color Paper

  • Supports logo or site name, mission, comment user pictures, shortcut icon, and primary and secondary links.
  • Fixed width layout with 2 columns, Maintenance/site off-line theme, CSS based, tableless design.
  • PNG fix for IE5.5+, comes with 5 variation of colours (teal, green, orange, pink, purple).


  • Site name, Site slogan, Mission statement, Top search box, Shortcut icon, Primary Links, User pictures in posts and comment
  • Tableless Layout,Top and Bottom content block regions, 3 Footer block regions
  • jQuery Transparent PNG Fix for IE6 and below (inside theme settings)
  • Bi-directional (BiDi) support

Dark Elegance

  • Light-weight and fast loading, Focus on minimal implementation
  • Fixed 2 Column Layout 950px, CSS based, tableless design.
  • Fully customizable header image [PSD Included], Support for logo, primary links, mission, search box, shortcut icon and user pictures


  • Tableless design, fixed width layout,
  • 2 columns with single right sideba, 3 footer block region, Top and bottom content block regions
  • Site nam, Site slogan, Mission statement, Top search box, Shortcut icon, Primary Links

Ebizon Exotic Red

  • Ebizon Exotic Red is a beautiful strict xHTML validated, standards compliant CSS based 2 Columns drupal template.

Ebizon RedFire

  • Ebizon RedFire is a strict xHTML validated, standards compliant CSS based drupal template with mission statement, breadcrumbs, custom footer.
  • It is a fixed width with beautiful red, black on white background color theme.


  • Supports site name, comment user pictures, shortcut icon, and primary links.
  • Fixed width layout with 3 columns, CSS based, tableless design.
  • Nifty rounded corners, Uses Whatever:hover script for IE6 and below support


  • Freestyle is a colorful, tableless, two column layout. Freestyle's skate/punk motif uses pink and yellow neon spray paint as a graffiti backdrop for a blocky stencil-like typeface.
  • It has nice positive and negative space usage and some subtle torn edge styling. It almost reminds you of that flyer for your band that you had your friend screen print copies of in his grandma's basement back in the day.

Fresh Media

  • Three special “user” block regions
  • Two-columns, Fixed width, tableless / Pure CSS design
  • Five block regions - content, right sidebar, footer 1, footer 2, and footer 3


  • This is a minimal and very clean theme, including a lot of white space, for those who love clean and minimal designs. It is very lightweight and fast loading.
  • The theme is tested with all major browsers.
  • Collapsible left sidebar and bottom blocks.


  • Fixed width with 2 columns
  • Cross-browser compatible, Optimized for fast loading
  • Standards-compliant XHTML 1.0 Strict and CSS


  • Fixed width with 2 columns
  • Standards-compliant XHTML 1.0 Strict and CSS
  • Cross browser compatible and tested on IE-6, IE-7, FireFox, Opera


  • It is a simple clean theme with semantic markup, ideal for blogs.
  • The mulpo theme manages to look very stylish with just one background image, all the rest is done with CSS.
  • Mulpo has only been tested in Firefox and Safari.


  • Based on a GPL licensed wordpress theme.


  • This theme is a blog theme for Drupal 6. The footer is designed to have 3 columns, so for the best aesthetic look, multiples of 3 are the best look for this theme (3, 6, 9 blocks).
  • jQuery used to hide/show the categories on node pages. Forum's are built based on the taxonomy system, so special attention was paid to how categories display on forum pages.
  • No logo on the theme.


  • Scruffy is a grungy, two-column blog theme originally designed for Wordpress by Cobus Bester.
  • The Drupal port preserves the same fundamental layout, with minor tweaks to work with non-node pages, Drupal status messages, and so on.

Strange Little Town

  • Site name, Site slogan, Mission statement, Primary Links, User pictures in posts and comment
  • Top and Bottom content block regions, tableless Layout, 1 Left, 1 Right, Both or None sidebars support
  • jQuery Transparent PNG Fix for IE6 and below (inside theme settings), Bi-directional (BiDi) support

The Morning After

  • This is a port of the Wordpress theme The Morning After to Drupal/ProsePoint, developed as a subtheme of Zen.
  • NOTE: You must install the Zen theme first! See http://drupal.org/project/zen.
Mar 31 2009
Mar 31

I admit I've been lurking in a very slackernly manner in all the discussions in the Sakai community about content authoring, 3akai, UX, K2, Sakai NG and other unpronounceables, so I'm sorry if all this is a day late and a dollar short. Feel free to ignore me if you're part of Sakai and are way too far gone for any more input. After all, these are just thought experiments ;) If you're not part of Sakai, you might learn something about Drupal at least, so it may well be worth your time.

I draw some lessons here from Twitter and Drupal not to suggest that Sakai duplicate them, but rather that we hold those models in mind as we move Sakai forward. Even without these experiments, some of these ideas may be in our thinking about Sakai, so if they are familiar, take it as a vote of confidence. But if not, I'd like us to have at least thought through why we would not take them as inspiration or why we would choose another path.

In the lessons I draw from Twitter and Drupal below, I may come off as a bit of a zealot. Frankly, I have a greater appreciation for Twitter and Drupal as tools that I have for Sakai as a tool—my greatest appreciation for Sakai has always been for its community. But I would like to appreciate Sakai-the-tool as much or more than Twitter and Drupal, and I think I could, given the directions I see Sakai heading now.

But why Twitter and Drupal? When I'm thinking about all this Sakai stuff, my first thought is to reach for existing models. And the models I reach for are the handy ones. Why? Because there must be some reason I keep certain tools handy. There are lots of good tools, but the ones that fit so comfortably in my hand are well-worn for a reason. I also know them well—keen edges and ugly nicks—and so can draw the best lessons from them.

For those of you who live under rocks, Twitter is a microblogging and social networking service that has gotten a bit of press lately. A lot of people are using Twitter, and a lot of people don't get it at all. If you already use Twitter, great. If you don't get it, that's OK. You don't need to "get" Twitter to learn its lesson. There's only one, it's pretty big picture, and you won't have to tweet about doing your laundry or hear about mine just because you read about it.

Drupal is a mature web content management system/application toolkit, currently at version 6.10, with a very vibrant international community and strong commercial ecosystem. About 1,400 people attended the most recent DrupalCon in Washington DC.

Keep It Simple Like Twitter

Keep it simple. Open it up. Let the complexity come from everywhere.

John Ellis has kidded that Twitter has become so popular mostly because it is so easy to make new words that start with "tw": twavatar, tweeple, tweetup, twistory, etc, and if you haven't heard them all, check out the twictionary: http://twictionary.com

I think John's almost right. It's about the simplicity and what people do with it. I think Twitter's rise has a lot to do with their focus on keeping it simple: 140 character posts, direct, addressed, or pure statement, public/private, following/followers, search. Twitter keeps it simple and—just as importantly—offers a public API that lets the world layer an almost unfathomable and—to the Twitter team I'm sure—unimagined variety of interfaces, uses and extensions based on Twitter's simple service.

In other words, Twitter knew what it was doing, but it didn't expect that what it was doing was all that could be done.

Neither can Sakai. Looking ahead: we should focus, keep it simple, do it well, and open it up, so that everything we can't yet imagine can hang off our work.

Draw Good Boundaries Like Drupal

One of the most crucial decisions for any information machine is to decide how specific it wants to be and where it will draw boundaries around what it will do.

Every piece of software I've been involved with seems to follow the same general development pattern: In the beginning, software is built to meet specific needs in a certain context. As more needs are layered on over time, the software becomes either more cluttered or more generalized—or both—and gets rather messy. No one knows anymore exactly what it is for or where its boundaries are, but we end up tethered to it in all its messy complexity.

Take MS Word, which is both highly generalized (name something you CAN'T do with Word) and overly cluttered (you have to manage the TOOLBARS in Word). At this point, Word is really neither a great word processor nor is it powerful enough to be our main content management interface. And yet we use it for both. We are stuck to this big, messy machine and we can't get loose (assuredly, there are also some other, non-technical reasons we are stuck to Word).

Sakai also started out meeting specific needs. And over time, Sakai too has become rather cluttered. Now it seems we are clearly at a turning point where we want to generalize. I think our success will depend on where and how we map Sakai's boundaries as we clean things up. Drupal provides an instructive model in the cartography of information machines.

Caveats: There are other models that might be just as instructive. Drupal is just the piece of software I know best that, in my opinion, matches Sakai's stature and has done a good job defining itself as an information machine. There are also many valid criticisms of Drupal. For example, I would never argue that Drupal's user interface is ideal. The lessons I think Sakai can take from Drupal are at a deeper, architectural level.

First, like Twitter, Drupal has done a good job of drawing boundaries around what should be core and what should be left outside. Drupal core is pretty clean, focused on key, common functions. Meanwhile, in Drupal's contribution space and beyond, it is rather messy. That is exactly as it should be. Good stuff comes out of that mess and some of it makes its way into Drupal core when the time and scope is right. Other stuff outside is fully mature and absolutely essential—for some. And for that reason, it will never become core, which is exactly as it should be. Core should not be defined by maturity, but by generality. There are a lot of ways that the Drupal community works to support both high innovation in the periphery and healthy boundaries at the core. Sakai should think carefully about where we put our borders and how we will support work inside and out.

Second, Drupal has done a good job of generalizing, focusing and simplifying its core functionality, and making core functions easily available to peripheral tools. If you do it right, all you need to build into a Drupal module is the specific functionality you need...everything else is a call to core. This makes it incredibly easy and quick to add functionality to Drupal—which fosters innovation—and also ensures that contributed modules participate fully in the larger Drupal machine. As we collaborate to define and build Sakai's next generation, we should look to mature models like Drupal that have a head start on clarifying and exposing core functionality.

Those are the general lessons I draw from Twitter and Drupal, so if you've had enough, you can stop reading here. Following are some more specific examples I draw from Drupal that relate to some of our recent discussions in Sakai.


Drupal starts with the idea that (almost) everything is a piece of content, starting from the same place on a conceptual and technological level as a "node." In Drupal, you augment the structure and/or functionality of these generic nodes by "decorating" them with additional structured data fields, workflow, etc. This way, all Drupal core has to concern itself with is the common structure (eg, common metadata like author, creation timestamp, etc) and common functionality (eg, access, CRUD, versioning, validation, input, etc) of nodes. More specific structure and/or functionality gets layered onto the basic node either through generic admin interfaces (eg, the Content Construction Kit, or CCK) or more tailored modules that make specially augmented nodes for specific purposes.

Want to create an event record? Create a new "event" content type, add a timestamp field that uses a mini-cal data entry widget. Click, click, done. Add location? Just decorate your event content type with a location field—oh, and then you'll have all the magic of a host of map integration modules at your disposal. Click, click, done. Want your events to link to location profiles? Create a separate "location" content type and add a node relation field to your event content type to link each event to a profile of its location. There, you just built a dynamic event web application in 15 minutes without calling your code monkey.

Another key Drupal module—Views—provides a generic query and output service for content. Need a table listing of all content meeting certain parameters, paginated in groups of 25 with sortable columns? Click, click, done. Want to offer that same content as a feed? Click, click, done. Want some completely different bucket of content, organized and presented in some other way? Again, click, click, done—and almost always with no coding required.

By generalizing core content in this way, Drupal handles it all consistently, but at the same time makes it easy to customize content for even the most complex needs—often with no coding required. Is it so easy faculty could do it? Maybe not without training, but you may not want end-users defining new content types willy nilly anyway. What the Drupal model offers is a way to lower the bar for meeting specialized content needs to a level that they can be met in minutes by someone with only a bit of training: a faculty power user, instructional designers, help desk staff, student assistants—crikey, even I can do it. Also, did I mention that Drupal content type definitions are exportable? Yes, you can define, export and share specialized content types.

Drupal understands that content creation and display is a core function, but it doesn't expect to know what YOUR content needs to be. Sakai would benefit with generalizing its content handling to Drupal's degree. As educators, we may feel that we are well-placed to define what a syllabus, a quiz, a discussion, a lecture podcast, or a portfolio should be. But as technologists, we will serve all the unforeseen ideas for what educational content might be far better by designing a solid, general framework on which our current—and future—ideas can be made manifest.


From the start, Drupal anticipated that taxonomy—which is just a fancy word for categorization or tagging—was an essential core function. Drupal enables you to define any number of category vocabularies, each having special characteristics (eg, freetagging, hierarchy, etc), each holding any number of terms, and each related to whatever specific content types you desire. Thus any content in Drupal can be categorized in multiple ways, with highly structured categories or freetag folksonomies—or both—for different purposes. Good stuff is baked into core, like returning content matching various categories by simply including boolean queries in the URL.

Following the model I've been stressing of core simplicity enabling unanticipated innovation, Drupal modules make use of the basic, core taxonomy service to do all sorts of unexpected things, like category-based access control, or category-based organic group creation and management. With taxonomy as powerful as Drupal's baked into core, Sakai too could enable all sorts of things that we may not have yet imagined.


Drupal's core presentation layer is the icing on the cake, which is exactly what presentation should be: icing. There's nothing worse than finding presentation baked into deeper levels of software, where it's static and hard to change. Drupal handles presentation as the final layer, enabling design to be very flexible and easy to modify. Want every user to be able to choose between three entirely different designs? Just load three themes and let the users choose for themselves. Need to offer a mobile version of your site? A dedicated mobile URL and/or some user agent sniffing can automatically deliver a theme optimized for mobile devices—oh, and there's a module that does all that for you (something you'll find again and again in Drupal). Need that new content type you just made to look different than every other piece of content on your site? Drop a custom theme template named for that content type in your theme's directory and your generic theme gets overridden automatically with your custom design—just for that special case.

The power of this theming model came when Drupal core stopped worrying about what the perfect presentation should look like and instead offered a way to deliver ANY presentation predictably with easy-to-build templates. In Sakai, the same power and flexibility would take us past the question of what Sakai SHOULD look like to the simple answer: Sakai looks like whatever you want it to look like.


Our next-generation Sakai authoring experiments are delivering some juicy tools to place different pieces of content and widgets in different parts of a page. Drupal offers two models that may help us refine the good work we're already doing.

Drupal core has long had the concepts of regions and blocks. Regions are areas of a page defined by a theme. A theme can have any number of regions laid out in any way. Blocks are bite-sized content or functionality: anything from a static welcome message, to a listing of recently updated content, to a user log in form. Blocks can be created individually by users or made available programmatically by Drupal core or contributed modules. Drupal core offers tools to map blocks to different page regions, and customize the visibility of blocks based on almost anything: user role, content type, authentication status, URL patterns, etc.

Drupal's region and block system is very flexible, but it is better suited for site administrators to define global page layouts than it is for individual users to author custom pages with varied content as we have been imagining in Sakai.

Panels is a module outside Drupal core that comes closer to what we've been imagining in Sakai: the ability for an individual user to place content and/or widgets exactly where they want on an individual page. Unfortunately, the authoring experience in panels is not anywhere near the kind of intuitive WYSIWYG experience we have been working toward in Sakai. However, Drupal panels offers all the ingredients we might want in a page authoring experience...we just need to cook and serve them differently.

I take several lessons for page authoring in Sakai from what works well in Drupal's layout tools of regions, blocks and panels. When laying out a page in Sakai, we should be able to choose from:

  • A library of predefined layouts, offering good, commonly-used page structures. Some of these layouts could be merely structural—empty containers waiting for me to fill them—defining something like Drupal's page regions (eg, a typical three-column layout with header and footer). Others could combine some empty regions for me to fill, along with other regions already filled with existing widgets (eg, a big, empty body region with a sidebar that has calendar, discussion and tagcloud widgets already in place). We should be able to export and import these predefined layouts. I should be able to tag layouts and see/browse tags from other users—but one should be able to tag everything in Sakai, so we don't ever need to state this requirement again, right?
  • The opportunity to author a new, custom layout, where I can design whatever structure I want. I should be able to tag, export and share my custom layout.
  • A library of widgets—not unlike Drupal blocks—that deliver either content or functionality. I should be able to search and browse global widgets supplied by the system, my own widgets, and ideally, widgets authored by other users I've subscribed to. I should be able to tag widgets and see/browse tags from other users.
  • The opportunity to author a new widget on the spot, thereby adding it to both the page I'm authoring right now and my widget library for use elsewhere. Making a new widget might be like making a view in Drupal: the ability to make some selection of content and display it in some form (eg, table, list, feed, etc). Making a new widget might be like something else too. Like Drupal, Sakai should offer new tools the opportunity to supply new widgets—and/or the opportunity for users to author new kinds of widgets.
  • The opportunity to author a piece of content on the spot, thereby adding it to both the page I'm authoring right now and whatever other collections that specific kind of content happens to live within (eg, pages, syllabi, tests, forum topics, etc). Like modules in Drupal, new tools in Sakai that define content should end up offering the chance to author in Sakai's standard authoring environment.
  • The opportunity to define under what circumstances a given layout/widget/content piece is visible. As in Drupal, I should be able to define who can see something and when they can see it. Default visibility should be baked into predefined layouts, widgets and content. And if I have the right access, I should be able to override default visibility.

Pluggable Authoring Tools & Filters

Drupal offers flexible frameworks for modules to supply different ways to get content in and spit it back out. While Sakai has been wedded to the oft-maligned FCKeditor for some time (yes, all the WYSIWYG tools have their drawbacks), Drupal offers the ability to plug in almost any authoring tool: plain old text, different WYSIWYG/WYSIWYM editors, various markup formats, etc. At the same time, Drupal offers the ability to define output filters that can clean up and/or enhance stored content when it is rendered. Drupal's filter on output strategy allows the same content (stored raw in the database) to be transformed differently depending on what filters are in use (which can even depend on user role or preference). Want anonymous users to see all your content translated into Pirate talk? Done. Again, Drupal core is not determining how stuff gets in and out, it instead provides a pluggable framework so we can decide for ourselves what we need. So many of Sakai's usability issues revolve around the rigidity of input and output, we would do well to adopt a pluggable model which opens possibilities beyond what we can anticipate.


Unfriendly to humans and search engine robots alike, Sakai has some of the ugliest URLs ever. It makes sense for a web application to have canonical URLs and it's hard to make them friendly, but there's no reason to show them to the world. Drupal solves the ugly URL problem by offering a core service for URL aliasing, so users themselves can define better URLs for their content. A valuable contributed module—pathauto—allows site administrators to define automatic URL aliasing rules for different canonical URLs, thus saving authors the aliasing task and enabling more structured aliasing patterns. Again, the lesson for Sakai is to fix our problems by offering flexible options rather than trying to bake in the final solution.


Drupal core has basic workflow baked in based on triggers and actions, where triggers are set to fire on certain events, in turn generating specific actions. For example, a workflow can be established to email a site owner (an action) every time new content is posted (a trigger). Once again, instead of providing all the ideal workflows we might imagine, Drupal provides a generic tool to build workflows, which we can use to build those we already know we need, as well as those we don't yet know we need. If only Sakai's sometimes idiosyncratic workflows were merely defaults, which I could change or replace as easily as I can in Drupal.

Installation Profiles

Many parts of Drupal can be exported/imported (eg, content types, views) or are modular (eg, modules, themes, filters) to allow for easy sharing and migration. One of the Drupal's most powerful tools is the installation profile: an automatic recipe to build a new Drupal site. Installation profiles set modules, themes and other configuration options when Drupal is first installed so you can distribute a pre-packaged Drupal recipe, optimized for specific purposes. If Sakai had installation profiles like Drupal, I could imagine distributions for different organizational types (K-12, community college, liberal arts college, research university, etc), different usage focuses (collaboration, portfolios, teaching and learning), or different languages, giving new adopters better starting places than a generic Sakai installation. As Sakai generalizes itself, we should also have a way to demonstrate and distribute best practices for specific uses.

Other Stuff

There are many other (smaller) lessons Sakai might take from Drupal. Some that come to mind include:

  • The core form API that lets modules safely offer forms with minimal work and modify others (including core forms) dynamically as needed.
  • The core multisite functionality that allows Drupal to run multiple sites from the same codebase, yet override and/or augment any part of any site as needed.
  • The core comment functionality that lets any piece of content include threaded comments.
  • The core support for automatic feeds.
  • The core menu functionality that allows navigation to be managed as its own kind of content.
  • Core support for OpenID authentication.
  • Sophisticated core caching mechanisms.

Finally, a Shout Out to Portfolios

Oddly enough, the part of Sakai that most reminds me of Drupal's generality is our portfolio toolset. It's not surprising that portfolios—maybe the least well-defined practices in teaching and learning—have led to the most generalized tools in Sakai. And yet, the most obvious complaint about Sakai portfolio tools is that they don't do anything at all. The fact is: Sakai portfolios can do almost anything. What's missing in portfolios is the easy tools to build them and the portable models to demonstrate their power. Sakai would do well to look inside to its portfolio tools—for inspiration to generalize, but also for caveats about what must be in place to make generalized tools usable and practical.

Mar 31 2009
Mar 31

Automated module conversion seems to be a hit!

In December 2008, the Deadwood module was made available for use without download on the Boombatower web site. In the three months since, nearly 600 modules have been uploaded to the site and run through its conversion routines.

This is very encouraging news for the entire Drupal community. My only regret is this heavy usage comes nearly a year after the official release of Drupal 6. As stated in my previous post, I continue to challenge and encourage us as a community to embrace the idea of having our contributed modules ready to deploy when the new core version is released. To this end, I am working on a new version of Deadwood (that will be part of the Coder project and be renamed to Coder Upgrade). My goal with the new release is to increase the percentage of core API changes handled by the conversion routines and to provide an API to assist developers to write conversion routines for non-core APIs that are referenced in other contributed modules.

Mar 31 2009
Mar 31

Automated module conversion seems to be a hit!

In December 2008, the Deadwood module was made available for use without download on the Boombatower web site. In the three months since, nearly 600 modules have been uploaded to the site and run through its conversion routines.

This is very encouraging news for the entire Drupal community. My only regret is this heavy usage comes nearly a year after the official release of Drupal 6. As stated in my previous post, I continue to challenge and encourage us as a community to embrace the idea of having our contributed modules ready to deploy when the new core version is released. To this end, I am working on a new version of Deadwood (that will be part of the Coder project and be renamed to Coder Upgrade). My goal with the new release is to increase the percentage of core API changes handled by the conversion routines and to provide an API to assist developers to write conversion routines for non-core APIs that are referenced in other contributed modules.

Mar 31 2009
Mar 31

created on Mon, 2009-03-30 16:07

The "featured content rotator" seems to have become a standard feature in our client sites - a front page device for promoting content, using nice "flashy" effects during auto-rotation between promoted items. For Drupal 5 sites I ended up always working off the same custom module I had built for the first one and having to tweak it according to different client requirements: Did they want tabs? Did they want pause and play buttons? Should navigation be triggered on tab click or on tab hover? And so on. I had been thinking to myself I should really get around to writing a one-module-fits-all solution, where these options would just be different configuration settings. Well, I am now certain I will never write such a module. Recently, we needed to implement a rotator feature for a D6 client site. I had heard vaguely that there were D6 modules available but until I came across this post in the Duplicated Modules Hall of Shame on groups.drupal.org I had no idea that so many developers had contributed their own version of this feature.

So I set about evaluating the strengths and weaknesses of the various alternatives and figured while I was at it I should draw up a full comparison to help others choose between them. The comparison document is under the "Comparisons of contributed modules" section in the Drupal Handbook and you can find it here. As I went through the different modules I really was incredulous at the amount of duplicated effort, and many of the developers still seem to have plans to enhance their modules' functionality in directions that would only bring them closer to others that are already there. However, I was happy to discover that the developers of two of the most impressive (and most similar!) options - Views Cycle and Views Rotator - are already discussing consolidation. Awesome rotator module developers unite - yay! :-)


Mar 30 2009
Mar 30

DupalCon DC usability study presentation

This thing was constructed on March 30, 2009, and it was categorized as Drupal.
You can follow comments through the RSS 2.0 feed. Both comments and trackbacks are closed.

Video footage of the presentation of Drupal Usability Study #3 at DrupalCon DC.

This thing was constructed by Becca .

You can follow comments through the RSS 2.0 feed. Both comments and trackbacks are closed.

« My thoughts on Drupal usability Kim Goodwin on project planning »
Mar 30 2009
Mar 30

drupal 6 included an upgrade to the built in logging functionality (watchdog). drupal 6 exposes a new hook, hook_watchdog which modules may implement to log Drupal events to custom destinations. it also includes two implementations, the dblog module which logs to the watchdog table, and the syslog module which logs to syslog.

with these upgrades, log4drupal is less critical addition to a drupal install, and i hesitated before providing a drupal 6 upgrade. however, eventually i decided that log4drupal is still a useful addition to a drupal development environment as log4drupal provides the following features still not provided by the upgraded drupal 6 watchdog implementation :

  • a java-style stacktrace including file and line numbers, showing the path of execution
  • automatic recursive printing of all variables passed to the log methods
  • ability to change the logging level on the fly

in addition, the drupal 6 version of log4drupal includes the following upgrades from the drupal 5 version

  • all messages sent to the watchdog method are also output via log4drupal
  • severity levels have been expanded to confirm to RFC 3164
  • log module now loaded during the drupal bootstrap phase so that messages may be added within hook_boot implementations.

you may download the drupal 6 version here. see below for general information on what this module is about and how it works.

what is log4drupal?

log4drupal is a simple api that writes messages to a log file. each message is tagged with a particular log priority level (e.g., debug, info, warn, error or emergency) and you may also set the overall log threshold for your system. only messages with a priority level above your system threshold are actually printed to your log file. the system threshold may changed at any time, using the log4drupal administrative interface. you may also specify a level above which a stack trace will be appended to each mesage.


don't forget to read the included README.txt file. before enabling this module you must install the Pear Log package on your server.

module options

the module options are very similar to the drupal 5 version, and are shown below.

log4drupal admin screen


log4drupal is best explained by example. suppose you had a module example.module containing the following code:

function example_user($op, &$edit, &$account, $category = NULL) {

  log_debug("The example_user method has been called for operation $op for account", $account);
  if($account->uid == 1) {
    log_warn("That nasty super-user is creeping around again!!");

if your logging level is set to debug and you stacktrace level is set to warn, your log file will contain the following messages. notice that the $account object is automatically rendered recursively.

[10:29:19 03/30/09] [debug] [example.module:5] The example_user method has been called for operation load for account
stdClass Object
    [uid] => 1
    [name] => admin
    [pass] => 350c27da74479768b5402673ce
    [mail] => [email protected]
    [mode] => 0
    [sort] => 0
    [threshold] => 0
    [theme] =>
    [signature] =>
    [created] => 1237827294
    [access] => 1238434111
    [login] => 1238429857
    [status] => 1
    [timezone] =>
    [language] =>
    [picture] =>
    [init] => [email protected]
    [data] => a:0:{}
    [roles] => Array
            [2] => authenticated user

[10:29:19 03/30/09] [warning] [example.module:8] That nasty super-user is creeping around again!!
  at /var/www/drupal/sites/all/modules/example/example.module:8
  at /var/www/drupal/modules/user/user.module:22
  at /var/www/drupal/modules/user/user.module:183
  at /var/www/drupal/modules/user/user.module:1125
  at /var/www/drupal/includes/menu.inc:410
  at /var/www/drupal/includes/menu.inc:653
  at /var/www/drupal/includes/menu.inc:1010
  at /var/www/drupal/includes/menu.inc:999
  at /var/www/drupal/includes/menu.inc:948
  at /var/www/drupal/includes/menu.inc:719
  at /var/www/drupal/modules/user/user.module:736
  at /var/www/drupal/includes/module.inc:450
  at /var/www/drupal/modules/block/block.module:473
  at /var/www/drupal/includes/theme.inc:1571
  at /var/www/drupal/includes/theme.inc:617
  at /var/www/drupal/includes/theme.inc:1765
  at /var/www/drupal/includes/theme.inc:658
  at /var/www/drupal/index.php:36

if your logging level is set to warn and you stacktrace level is set to error, your log file will contain the following messages. notice that the debug message is no longer printed at all, and the warn message no longer includes a stacktrace.

[10:40:06 03/30/09] [warning] [example.module:8] That nasty super-user is creeping around again!!

all watchdog messages will also appear in your log4drupal log file. for example, as long as your logging level is set to notice or below, you will see the following message in your log file each time a user logs in

[11:02:43 03/30/09] [notice] [user.module:1368] Session opened for admin.

suggestions for new features always welcome.

Mar 30 2009
Mar 30
Share this

This panel will begin with a demonstration and discussion of the current state of the ongoing development of the Media module, and a thorough examination of the concept for its extensible API. Finally, we'll discuss the near and far-term plans, including the Media Sprint planned for the next day of the Open Media Camp.

The Media module, and its included Resource module, is the focal point of a multi-pronged effort to revolutionize media handling within Drupal, by backporting proposed core patches to Drupal into Drupal 6. These include utilizing PHP Stream Wrappers to encapsulate any file stream (local or remote) within the standard Drupal file API, and creating an API for a unified GUI, suitable as a drop-in supplement and/or replacement for the core Upload module, FileField/ImageField, Embedded Media Field, and other similar modules. By creating a robust media handling API, this frees future multimedia development from needing to reinvent various media and file-handing components.

This endeavor is fully backed with the participation of many other developers involved in Drupal multimedia, including Darrel O'Pry (dopry), Andrew Morton (drewish), Roger López (Roger López), Gus Austin (gusaus), and many others.

Mar 29 2009
Mar 29

Over the weekend I upgrade this blog to Drupal 6 so I could take advantage of all the advancements that have been made in Drupal core and some modules that only have releases for 6.x. While doing the upgrade, I also decided that I'd create a new theme because I'd never really liked the old one.

I'm not much of a designer, so I took a lot of the images and CSS from the Admire Gray theme, by WorthaPost, which I love, but actually turned it into a Zen sub-theme because I really like some of Zen's unique features. I also took a lot of inspiration from CopyBlogger, ShoeMoney and ProBlogger for certain elements.

I still need to clean up a few things like the comments, but overall I'm really happy with how it turned out, except for my lame attempt at a logo which looks a bit dull and boring. If there are any designers that want to give some suggestions, I'm listening!

Mar 29 2009
Mar 29

Cindy, cat herderIn my post last week I mentioned that we had a professional cat herder, Cindy McCourt, for the Toronto Drupal documentation sprint and that the entire approach was a bit new and different for us. It was certainly different than anything I'd done before, especially in the Open Source or Drupal world. I should start by noting that all of this grew from community efforts by a number of people and isn't any kind of brainchild of mine. This sprint was an awesome showing of how Drupal contributors can do amazing things.

A Drupalcon beginning

At the Drupalcon doc sprint, Cindy showed up with no laptop and a desire to help. She had already jumped in to help us organize the Drupalcon sprint on the fly and so I asked her if she could help me get myself together for the Toronto sprint. The sprint topic was so diffuse and huge (make Drupal docs better) that I wasn't sure what I needed to do to make it successful. There were a number of folks asking some high-level questions at Drupalcon so we agreed to have an impromptu meeting out in the corridor to discuss what needs to happen for Drupal docs.

In the Drupalcon meeting, Cindy did what I now recognize as a totally off-the-cuff meeting facilitation, as she tried to understand what the major concerns and goals of the Toronto sprint were trying to address. I came to learn about a whole new skill set that Cindy happens to specialize in: meeting facilitation. In the end, she and Emma Jane Hogbin spent most of the day working out, not just an agenda for the Toronto sprint, but also hammering together a process by which we could walk out of it with something tangible. This was exactly what I had been looking for. It only made sense to ask Cindy if she would be willing to come to Toronto to guide us through the plan she and Emma had started to craft. Luckily, she had the time free and enthusiastically agreed. Having an agenda is one thing, but getting through it is another. I welcomed the idea of having an expert to guide us.

The sprint

When we finally all got ourselves together in the hotel room Saturday morning, we talked about the weekend game plan. We started by setting out the vision of our ultimate target and making sure we were all on the same page. This included discussing the Drupal culture that surrounded our whole process and making sure we all understood the perspective we were working from. We also established rules for the weekend (including that Cindy could tell us to shut up if we got off track) and declared that while solutions are cool, we did not have time to be distracted with those details. Cindy declared anything that was a potential, specific solution to be implemented would go to the "parking lot" list and we would keep moving.

Once we had the ground rules laid and some caffeine in us, Cindy led us through the agenda. Having a targeted agenda set up ahead of time was a huge help, but the real success of the weekend was because Cindy was walking us through it, keeping us on track and largely being an impartial facilitator, rather than an active doc team participant. We systematically broke up the big issues, brainstormed, organized and then dove the next level down, brainstormed more, etc. Cindy let us ramble, wrote down all the ideas flying around and then helped us make sense of the storm and distill the actionable items from it. We looked at barriers, defined goals to address them and got down to nitty-gritty tasks to get there. We went from "OMG, this is an impossibly big goal" to "These are the steps to accomplish xyz." It was an amazingly organized, yet completely free-flowing process.

In addition to this process of chunking things up into manageable pieces and tasks, Cindy also had an overall "game plan" chart for us to look at from the big picture level. We spent the weekend drilling down through the overall vision, the goals that we want to hit and the tasks that could make them happen. We wrapped up the weekend by looking at the big picture again and talking about other factors that come in to play, like people, ever-present barriers to be aware of, as well as the elements of success. This structure of the target and the ways we can get there are what will be coming out in a kind of "doc map," hopefully in the next week or so (I've still got plenty of writing and mapping to do, but I'm working on it as much as I can).

Eye-opening contribution

Now, I have never taken part in a meeting like this before and I walked out of it pretty much blown away by how effective it had been. I have to say that Cindy was amazing. She knows her stuff and I was really, really impressed with how responsive and adaptable she was through the whole process, starting at Drupalcon, all the way through. Aside from having a lot of experience and knowing the ropes of the process, she is an extraordinary listener. She learns and improvises on the fly at an amazing rate, while making the whole ride as seamless as possible. So, she not only made our sprint rock, but she has opened my eyes to a new way of approaching big, gnarly goals. She has skills to offer our community that I hadn't even seen before and I am sooo glad that she offered to contribute in this way. I am totally stoked about Drupal docs and I love that we have people like Cindy as part of our community helping us make them better.

Mar 27 2009
Mar 27

One of Google's current experiments enables participants to use options for restricting search results by certain criteria or to use tools like the wonder wheel for related query suggestions on Google's search result pages.

In this screencast you can see how some of these new search tools, e. g. the timeline and image view, look like and what Google's wonder wheel suggests when searching for Drupal.

[embedded content]

If you want to try this yourself and are not based in the US or for some reason don't want to participate in the experiment, paste the following JavaScript code in the address bar of your browser when on google.com and hit return to set the cookie, as demonstrated in the video. Have fun!

javascript:void(document.cookie="PREF=ID=4a609673baf685b5:TB=2:LD=en:CR=2:TM=1227543998:LM=1233568652:DV=AA:GM=1:IG=3:S=yFGqYec2D7L0wgxW;path=/; domain=.google.com");

Via Google Blogoscoped

Mar 26 2009
Mar 26

installing drupal is pretty easy, but it's even easier if you have a step by step guide. i've written one that will produce a basic working configuration with drupal6 on debian lenny with php5, mysql5 and apache2.

all commands that follow assume that you are the root user.

let's get started!

install the dependencies

# apt-get install mysql-server
# apt-get install apache2
# apt-get install php5
# apt-get install php5-mysql
# apt-get install php5-gd

there aren't many options given when installing those packages. you may set a root password for mysql if you like (or not - it doesn't matter). next, restart apache to make it aware of the php installation.

# /etc/init.d/apache2 restart

verify your base apache install

if you've configured DNS with your hosting provider properly, when you go to your browser and type in http://www.example.com you should see the message "It Works!". if you don't, stop here and find somebody to help you with DNS and apache before continuing with these instructions.

download and extract drupal

start with the drupal homepage, and find the Download Drupal 6.x link. In the code below, you'll need to replace the 6.X with the version you are actually downloading.

# cd /tmp
# wget http://ftp.drupal.org/files/projects/drupal-6.X.tar.gz
# gunzip drupal-6.X.tar.gz
# tar -xvf drupal-6.X.tar

here these instructions differ slightly from those provided with your drupal install. the packaged instructions suggest putting all the drupal directories directly inside /var/www. i prefer to contain them within a /drupal directory. if you are running several sub-domains on this apache server, this is a preferable set-up.

below, we move all the drupal stuff to =/var/www/drupal= and set various permissions appropriately

# mkdir /var/www/drupal
# mv drupal-6.10/*  /var/www/drupal/
# #  cd /var/www/drupal
# mv sites/default/default.settings.php sites/default/settings.php
# chmod o+w sites/default/settings.php
# chmod o+w sites/default
# chown -R www-data.www-data /var/www/drupal

set-up mysql

in this example, we create a database called drupaldb, a user called drupal with password lemon

first, create the drupaldb database.

#mysqladmin -p create drupaldb

next, create the drupal mysql user and set the permissions and password appropriately. note - the drupal user is a mysql user - not a linux shell user.

# mysql -p
TEMPORARY TABLES, LOCK TABLES ON drupaldb.* TO 'drupal'@'localhost'  IDENTIFIED BY 'lemon';

finally, tell drupal what you did

# cd /var/www/drupal
# vi sites/default/settings.php

find the line that starts with $db_url and change it to

$db_url = 'mysql://drupal:[email protected]/drupaldb';

fire up drupal

go to your browser and type http://www.example.com/drupal/index.php. you will be redirected to http://www.example.com/drupal/install.php?profile=default. (note: if you are NOT automatically redirected to install.php, and instead get a page full of SQL errors, just proceed manually to install.php). follow the instructions to set up your super-user account.

enable clean urls in apache (optional)

add the following to /etc/apache2/sites-available/default just above the closing </VirtualHost> tag.

<Directory /var/www/drupal>
   Options -Indexes FollowSymLinks MultiViews
   AllowOverride All
   Order allow,deny
   allow from all

make sure that mod-rewrite is enabled, and then restart apache.

# a2enmod rewrite
# /etc/init.d/apache2 restart

now go the URL http://www.example.com/drupal/?q=admin/settings/clean-urls, take the test (hopefully you'll pass) and, when you do, turn on clean urls.

set up an apache virtual host (optional)

it's nice to setup an apache virtual host for your drupal site. this allows you to create custom logging, remove the /drupal/ from your urls and nicely encapsulate the directives for drupal. here's how you can do it.

create a file in /etc/apache2/sites-available called www.example.com that looks something like this:

<VirtualHost *>
   ServerName myserver.mydomain.com
   DocumentRoot /var/www/drupal
        <Directory />
                Options -Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        ErrorLog /var/log/apache2/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined

now, check the file called default in this same directory. make sure the top two lines say the following

NameVirtualHost *
<VirtualHost *>

finally, enable your new virtual host and restart apache one more time.

# a2ensite www.example.com
# /etc/init.d/apache2 restart

go to your browser and visit http://www.example.com. if you still see the apache default page ("It Works!") instead of your drupal home page, just delete the default index.html file

# rm /var/www/index.html

Mar 26 2009
Mar 26

Attached below are the slides for the March, 2009 ASU Drupal Users Group presentation I gave. The presentation contains info on the following topics:

DrupalCon 2009: Washington, DC



Miscellaneous Links

Mar 26 2009
Mar 26

My thoughts on Drupal usability

This thing was constructed on March 26, 2009, and it was categorized as Drupal.
You can follow comments through the RSS 2.0 feed. Both comments and trackbacks are closed.

Kent Bye of Lullabot interviewed me (and other team members, as well as a whole lot of other Drupal community members) at Drupalcon. Take a listen to the interview.

This thing was constructed by Becca .

You can follow comments through the RSS 2.0 feed. Both comments and trackbacks are closed.

« Tricks from #drupalusability DupalCon DC usability study presentation »
Mar 26 2009
Mar 26

Just wanted to let you know that there's a new DrupalEasy podcast (#3) now out there.  If you haven't listened to  our podcast I'd highly recommend that you do if you do any work at all with Drupal (or if you're interested in working with Drupal).  We cover, Drupalcon, SXSW, Setting up a Drupal Theme with Artisteer, the 2009 Google Summer of Code and of course, our module picks of the week!

Mar 24 2009
Mar 24

Create a new block or page with Full HTML input format access. The following javascript will redirect you to the node number without having to highlight just the right part of the URL.

Enter a node number in the box below. Clicking Submit will redirect you to it.

<script type="text/javascript">
function handleThis(formElm)
window.location="/node/" + formElm.nid.value + "";
return false;
<form onsubmit="return handleThis(this)">
<input type="text" name="nid" />
<input type="submit" value="Submit" />

Depending on your site configuration, you might need to alter the window.location value for not redirecting directly to the root of the URL, in which case an absolute URL might work best.

Mar 24 2009
Mar 24


I have been inspired by your work in the Drupal community. I watched your video and downloaded your notes on YouDrup which has been essential for starting my Drupal career. I just visited your site and am sad to hear about your health issues. I have heard a little about ALS and know some researchers who know about ALS and other neurological conditions such as multiple sclerosis (MS) and they have taught me a bit about neurodegenerative diseases. In particular, I have spent a bit of time studying MS. I don't know much about your ALS but know that a doctor from Australia, Prof. Thomas Borody, has recently published several reversals of MS where people have left wheelchairs. Borody is not a quack, but a cutting-edge GI doc who actually invented the antibiotic cocktail therapy for stomach ulcers. Up to now, MS has been regarded as an incurable disease. His discovery was an accident as he is a world famous gastroenterologist who was treating MS patients for constipation by replacing their bowel flora. By accident they left the wheel chairs and no longer have MS. This is not hocus-pocus but rather some newly reported information that was published in October 2011 so it is fairly new and the science is cutting-edge. This information was released at a normal American College of Gastroenterology conference in Washington DC.

Also a research professor of medicine, Dr. Terry Wahls from Iowa, reported reversing her MS with a very specific diet which inevitably would change the chemistries in the bowel also, even though she did not mention this possible explanation in her videos.

I don't know how these discoveries could affect your situation but I suggest you look into it. If you haven't looked already, go to http://www.pubmed.gov to find the latest research on ALS for yourself. Practicing doctors are often decades behind the research in the labs and many have helped themselves from tough illnesses from the published research there. There is a website that discusses new research in MS at http://nubiome.com/blog/cutting-edge-multiple-sclerosis-research/ . If you review all of the information on the site, you can start to see the dots connecting between neurology, gastroenterology, immunology, and cardiovascular fields. In particular, unknown bowel bacteria creating chemistries that cause MS. It doesn't seem like too big a stretch to think that ALS could have a different set of chemistries involved that are also caused by undesirable chemistries from the bacteria bowel. Perhaps learning about the bacteria interactions will help you find a safe therapy.

A problem with medical research so far is that each branch of medicine (neurology, immunology, cardiology, etc.) seems to be fairly compartmentalized into silos with little cross-communication. From this MS discovery, it clearly shows that scientists need to look outside the central nervous system to find the root causes and therapies of the "incurable" neurological diseases. The lack of this activity is probably why these conditions have not yet been cured. However, this new announcement will surely accelerate new research and treatments for ALS and I hope can have an impact on your situation.

Take care

Mar 21 2009
Mar 21

I have an installation with multiple Drupal sites in one install (Drupal multisite). One of the multisites needs information from another multisite's nodes which use CCK. I've done such things before with direct, custom queries, but it's always bothered me that the CCK fields could shift around on me and my queries break. This time I'm trying to use Views2.

Let's say the site that has the information I want is #1 and the site querying the data is #2. I made the view that gets the data I want in site #1. It works perfectly. Then since I don't really want a formatted display of the data, I whipped up a tiny module to use views_get_view_result() in site #1 to make sure it returned an array that would be something I could use; it was.

Note here that the view is configured to be unrestricted access. It queries nid, author, a rolereference field, and a date field. The fields are managed in #1 by content_permissions module and the node by workflow_access. With all that node configuration and filters for the rolereference and workflow of the node, it still showed the view correctly on #1 through views_get_view_result().

I took exactly the same code I used for views_get_view_result() and put it on site #2, but I wrapped it in a db_prefix changer. The idea I thought would be that Drupal would just temporarily switch database tables and then switch right back transparently. Then I activated all the same workflow, CCK, and views modules on #2 to make sure there wouldn't be any missing modules that #1 needed to put up the same view result.

= $GLOBALS['db_prefix'];
$GLOBALS['db_prefix'] = 'number_one_';
$view = views_get_view_result('my_view_name');
$GLOBALS['db_prefix'] = $old_db_prefix;

This almost works to query the data I want from #1, except it doesn't return the CCK fields, only the nid and author. I did a little bit of debugging and found that in views_get_view_result(), the $view object handler for the CCK fields is listed as views_handler_field_broken.

Before I did some debugging to find the reference to views_handler_field_broken, I thought perhaps with the permissions modules on #1, it was a field access issue. I'm logged in as UID 1 on #2, I copied a $user object from a UID 1 session on #1, I inserted a session in the sessions table on #1, and I tried faking a masquerade, so I'm pretty sure it's not a permissions issue since I should be pretending to be UID 1 on #1 when that view executes.

I've tried re-installing views, CCK, the widgets, and workflow on #2 to make sure all the various parts were available to views when it came time to execute the view on #1 during the db_prefix switch. What I'm wondering now is whether CCK does some sort of hook_init() static variable field caching on #2 so that when it gets time to find those CCK fields I want on #1, they're not in the cache. Someone else suggested that perhaps I needed to re-execute some part of bootstrapping after I switch db_prefix, and then again after I switch back. I'm really not sure where to go next for getting those CCK fields to display and the doxygen stuff I found on views_handler_field_broken isn't very detailed on the reasons why it would be used as the handler. Perhaps there's an even better way than swapping out db_prefix and I can't see it cause I'm stuck in db_prefixing land.

A solution:

I figured out a hack that involves refreshing some CCK cache and preventing views from caching by hacking views.

After switching to the #2 db_prefix, I call content_clear_type_cache(TRUE); then comment out the static $cache variable in _views_fetch_data(). I see that _views_fetch_data() calls hook_views_data_alter, but that is executed before I switch to the #2 db_prefix and does not run again as long as the static $cache variable is set.

I still have a little bit of hope there's a way to do this without hacking up views. I saw this in view::execute() that makes me think perhaps there's something I could do when configuring a view in #1 perhaps that would reference data in #2:

// Allow for a view to query an external database.
if (isset($this->base_database)) {
$external = TRUE;

Mar 20 2009
Mar 20

After the announcement of our testing service I asked for feedback from prominent community members. The feedback was overwhelmingly positive with some notable quotes being:

Usability testing of Drupal 7 would have been virtually impossible if it weren't for the automated testing in place keeping core stable. Drupal 7 HEAD is much more stable than any release we [have] ever had. It easily saved me a 100 hours knowing I didn't break something I wrote an hour ago. I'm not sure I would have been able to have completed it [DBNTG]. Testing.drupal.org went live in October 2008, and once again, Drupal's development process was reveolutionized. Now, developers don't need to sit through a test run (which could take 30 minutes or more) in order to verify their changes are working; they can simply upload their changes and be informed by one of the testing clients.

In order to allow Drupal shops to gain the same advantages that Drupal core has received we offer our testing service. Through the service we will maintain an automated testing network similar to testing.drupal.org for use by our clients. In addition we can review your tests to ensure that they are up to standards and provide feedback on ways to improve them.

We are currently working to provide testing of "data sets" which is extremely useful for testing changes against deployed sites. The data from a deployed site can be backed up and tests run against that dataset to ensure that code changes do not break custom workflows or configurations. Testing of data sets does not replace functional testing like that used in Drupal 7 core, but it provides an additional layer of confidence when deploying changes to a live site.

Mar 19 2009
Mar 19

I often have a hard time deciding whether to use a CCK field or the taxonomy module when building Drupal sites. At Drupalcon, I was glad to see that I am not alone in my confusion. At the Drupalcon Drupal Taxonomy Revisted session, I finally started to understand the use case for each.

Here’s a table I put together to help me quickly decide whether to use taxonomy or CCK in the future.

Question Which to Use? Rationale Do you have a lot of terms or attributes? As the size of your vocabulary or field option list grows, taxonomy becomes a better choice CCK stores its values as text while taxonomy stores values with an ID. This makes lookups over a large data set more efficient for taxonomy. Are you using a hierarchy? Taxonomy Taxonomy is designed to handle multiple levels of hierarchy, which a CCK field is not Are you listing attributes? For example, listing the color options of a car. CCK CCK makes more sense if you have created a content type and are adding attributes to it using CCK fields. For example, I could have a car node type and color would be a CCK field Does your piece of content exist in the real world on its own? Taxonomy Taxonomy terms are designed to map to real-world objects in a way that CCK fields are not. For example, if I have a taxonomy of US States, each state exists whether or not I have assigned content to it. Will you re-use your term or attribute in multiple ways within your site or re-organize them? Taxonomy If you have a classification such as US States that you plan to use in multiple node types, then taxonomy makes more sense. It is easier to add new terms to taxonomies over time than to individual CCK fields. Are you using CCK or taxonomy to list critical information on your site? What is the cost of losing the data if you upgrade to a future major Drupal version? Taxonomy Taxonomy is more futureproof because each term has its own unique id, and, it can be moved between vocabularies. Taxonomy is also a Drupal core module and there will almost certainly be an easy upgrade path from Drupal 6 taxonomy to Drupal 7 taxonomy.

An Example: Classifying Topic Areas

Using this criteria, making the decisions I was stuck on in an earlier blog post becomes a lot easier.

Question Response Decision Do you have a lot of terms or attributes? Yes, we have at least 200 terms and that number is likely to grow dramatically over the next few years. Taxonomy Are you using a hierarchy? Yes, we have at least 3 levels of hierarchy. Taxonomy Are you listing attributes? For example, listing the color options of a car. No, we are listing topics that span multiple content types. Taxonomy Does your piece of content exist in the real world on its own? Somewhat. Greenhouse Gas Inventories exist in the real-world, as does the “Climate.” The category “Campus Operations” is more of a grey area Probably Taxonomy Will you re-use your term or attribute in multiple ways within your site or re-organize them? Yes, we plan to classify many different node types with the same terms Taxonomy Are you using CCK or taxonomy to list critical information on your site? What is the cost of losing the data if you upgrade to a future major Drupal version? It would be painful to lose all of our classification information but I don’t think that it would destroy us as an organization. CCK or Taxonomy

After evaluating which to use with my new handy chart, it’s clear the taxonomy makes more sense for classifying our topical areas.

Reblog this post [with Zemanta]
Mar 19 2009
Mar 19

For some work projects we've started making all the configuration changes via update functions. These get checked into version control and from there deployed to the staging site for testing, and then eventually deployed on the production site. The nice thing about update functions is that you can test it on staging and be sure that exactly the same changes will occur on the production site.

Here's a few examples, I'll continue to update it as I get more good examples.

Installing a module

Simple one liner to enable several modules:

function foo_update_6000(&$sandbox) {
$ret = array();
drupal_install_modules(array('devel', 'devel_node_access'));

Batch based update to regenerate PathAuto aliases

More elaborate update that uses the BatchAPI to avoid timeouts while regenerating the path aliases for two node types:

function foo_update_6000(&$sandbox) {
$ret = array();  if (!isset($sandbox['progress'])) {
// Set the patterns
variable_set('pathauto_node_foo_pattern', 'foo/view/[nid]');
variable_set('pathauto_node_bar_pattern', 'bar/view/[nid]');    // Initialize batch update information.
$sandbox['progress'] = 0;
$sandbox['last_processed'] = -1;
$sandbox['max'] = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE n.type IN ('foo', 'bar')"));
// Fetch a group of node ids to update.
$nids = array();
$result = db_query_range("SELECT n.nid FROM {node} n WHERE n.type IN ('foo', 'bar') AND n.nid > %d ORDER BY n.nid", array($sandbox['last_processed']), 0, 50);
  while (
$node = db_fetch_object($result)) {
$nids[] = $node->nid;
  }  if (
$nids) {
// Regenerate the aliases for the nodes.
pathauto_node_operations_update($nids);    // Update our progress information for the batch update.
$sandbox['progress'] += count($nids);
$sandbox['last_processed'] = end($nids);
// Indicate our current progress to the batch update system. If there's no
  // max value then there's nothing to update and we're finished.
$ret['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);  return $ret;

Change node settings

Make a few changes to the node type settings:

function foo_update_6001() {
$ret = array();  // Change the teaser label to 'teaser text'.
$ret[] = update_sql("UPDATE content_node_field_instance SET label = 'Teaser text' WHERE field_name = 'field_teaser'");  // Change the 'description' and 'biography' labels to 'body text'.
$ret[] = update_sql("UPDATE content_node_field_instance SET label = 'Body text' WHERE field_name IN ('field_description', 'field_bio')");  // Rename the front node type 'Front Page' to 'Front Page Configuration'
$ret[] = update_sql("UPDATE node_type SET name = 'Front Page Configuration' WHERE type = 'front'");  return $ret;

Delete a bunch of views

I exported the site's views into a default views and needed to remove the existing ones from the database.

function foo_update_6001(&$sandbox) {
$ret = array();  // Since we're shipping default views delete the versions from the database.
if (!isset($sandbox['progress'])) {
// Initialize batch update information.
$sandbox['progress'] = 0;
$sandbox['views'] = array(
// ...
$sandbox['max'] = count($sandbox['views']);
module_load_include('module', 'views');
$view_id = $sandbox['views'][$sandbox['progress']];
  if (
$view = views_get_view($view_id)) {
$sandbox['progress']++;  // Indicate our current progress to the batch update system. If there's no
  // max value then there's nothing to update and we're finished.
$ret['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);  return $ret;
Mar 19 2009
Mar 19

There was no shortage of kick-a$$ sessions at the recent DrupalCon DC. The ones that really did it for me, however, were those that dealt with the thorny topic of deployment and migration. This is something that I've been thinking about for quite a long time, and it's great to see that a lot of other Drupal people have been doing likewise.

The thorniness of the topic is not unique to Drupal. It's a tough issue for any system that stores a lot of data in a relational database. Deploying files is easy: because files can be managed by any number of modern VCSes, it's a snap to version, to compare, to merge and to deploy them. But none of this is easily available when dealing with databases. The deployment problem is similar for all of the popular open source CMSes. There are also solutions available for many systems, but they tend to vary widely in their approach and in their effectiveness. In Drupal's case, the problem is exacerbated by the fact that a range of different types of data are stored together in the database (e.g. content, users, config settings, logs). What's more, different use cases call for different strategies regarding what to stage, and what to "edit live".

Context, Spaces and Exportables

The fine folks from Development Seed gave a talk entitled: "A Paradigm for Reusable Drupal Features". I understand that they first presented the Context and Spaces modules about six months ago, back in Szeged. At the time, these modules generated quite a buzz in the community. Sadly, I wasn't able to make it to Szeged; just as well, then, that I finally managed to hear about them in DC.

Context and Spaces alone don't strike me as particularly revolutionary tools. The functionality that they offer is certainly cool, and it will certainly change the way we make Drupal sites, but I heard several people at the conference describe them as "just an alternative to Panels", and I think that pretty well sums it up. These modules won't rock your world.

Exportables, however, will.

The concept of exportables is simply the idea that any piece of data that gets stored in a Drupal database, by any module, should be able to be exported as a chunk of executable PHP code. Just think of the built-in "export" feature in Views. Now think of export (and import) being as easy as that for any Drupal data — e.g. nodes, users, terms, even configuration variables. Exportables isn't an essential part of the Context and Spaces system, but it has been made an integral part of it, because Context and Spaces allows for most data entities in core to be exported (and imported) as exportables, and because Context and Spaces wants all other modules to similarly allow for their data entities to be handled as exportables.

The "exportables" approach to deployment has these features:

  • The export code can be parsed by PHP, and can then be passed directly to Drupal's standard foo_save() functions on import. This means minimal overhead in parsing or transforming the data, because the exported code is (literally) exactly what Drupal needs in order to programatically restore the data to the database.
  • Raw PHP code is easier for Drupal developers to read and to play with than YetAnotherXMLFormat or MyStrangeCustomTextFormat.
  • Exportables aren't tied directly to Drupal's database structure — instead, they're tied to the accepted input of its standard API functions. This makes the exported data less fragile between Drupal versions and Drupal instances, especially compared to e.g. raw SQL export/import.
  • Exportables generally rely on data entities that have a unique string identifier. This makes them difficult to apply, because most entities in Drupal's database currently only have numeric IDs. Numeric, auto-incrementing IDs are hard for exportables to deal with, because they cause conflict when deploying data from one site to another (numeric IDs are not unique between Drupal instances). The solution to this is to encourage the wider use of string-based, globally unique IDs in Drupal.
  • Exportables can be exported to files, which can then be managed using a super-cool VCS, just like any other files.

Using exportables as a deployment and migration strategy for Drupal strikes me as ingenious in its simplicity. It's one of those solutions that it's easy to look at, and say: "naaaaahhhh… that's too simple, it's not powerful enough"; whereas we should instead be looking at it, and saying: "woooaaahhh… that's so simple, yet so powerful!" I have high hopes for Context + Spaces + Exportables becoming the tool of choice for moving database changes from one Drupal site to another.

Deploy module

Greg Dunlap was one of the people who hosted the DC/DC Staging and Deployment Panel Discussion. In this session, he presented the Deploy module. Deploy really blew me away. The funny thing was, I'd had an idea forming in my head for a few days prior to the conference, and it had gone something like this:

"Gee, wouldn't it be great if there was a module that just let you select a bunch of data items [on a staging Drupal site], through a nice easy UI, and that deployed those items to your live site, using web services or something?"

Well, that's exactly what Deploy does! It can handle most of the database-stored entities in Drupal core, and it can push your data from one Drupal instance to another, using nothing but a bit of XML-RPC magic, along with Drupal's (un)standard foo_get() and foo_save() functions. Greg (aka heyrocker) gave a live demo during the session, and it was basically a wet dream for anyone who's ever dealt with ongoing deployment and change management on a Drupal site.

Deploy is very cool, and it's very accessible. It makes database change deployment as easy as a point-and-click operation, which is great, because it means that anyone can now manage a complex Drupal environment that has more than just a single production instance. However, it lacks most of the advantages of exportables; particularly, it doesn't allow exporting to files, so you miss out on the opportunity to version and to compare the contents of your database. Perhaps the ultimate tool would be to have a Deploy-like front-end built on top of an Exportables framework? Anyway, Deploy is a great piece of work, and it's possible that it will become part of the standard toolbox for maintainers of small- and medium-sized Drupal sites.

Other solutions

The other solutions presented at the Staging and Deployment Panel Discussion were:

  • Sacha Chua from IBM gave an overview of her "approach" to deployment, which is basically a manual one. Sacha keeps careful track of all the database changes that she makes on a staging site, and she then writes a code version of all those changes in a .install file script. Her only rule is: "define everything in code, don't have anything solely in the database". This is a great rule in theory, but in practice it's currently a lot of manual work to rigorously implement. She exports whatever she can as raw PHP (e.g. views and CCK types are pretty easy), and she has a bunch of PHP helper scripts to automate exporting the rest (and she has promised to share these…), but basically this approach still needs a lot of work before it's efficient enough that we can expect most developers to adopt it.
  • Kathleen Murtagh presented the DBScripts module, which is her system of dealing with the deployment problem. The DBScripts approach is basically to deploy database changes by dumping, syncing and merging at the MySQL / filesystem level. This is hardly an ideal approach: dealing with raw SQL dumps can get messy at the best of times. However, DBScripts is apparently stable and can perform its job effectively, so I guess that Kathleen knows how to wade through that mess, and come out clean on the other side. DBScripts will probably be superseded by alternative solutions in the future; but for now, it's one of the better options out there that actually works.
  • Shaun Haber from Warner Bros Records talked about the scripts that he uses for deployment, which are (I think?) XML-based, and which attempt to manually merge data where there may potentially be conflicting numeric IDs between Drupal instances. These scripts were not demo'ed, and they sound kinda nasty — there was a lot of talk about "pushing up" IDs in one instance, in order to merge in data from another instance, and other similarly dangerous operations. The Warner Records solution is custom and hacky, but it does work, and it's a reflection of the measures that people are prepared to take in order to get a viable deployment solution, for lack of an accepted standard one as yet.

There were also other presentations given at DC/DC, that dealt with the deployment and migration topic:

  • Moshe Weitzman and Mike Ryan (from Cyrve) gave the talk "Migration: not just for the birds", where they demo'ed the cool new Table Wizard module, a generic tool that they developed to assist with large-scale data migration from any legacy CMS into Drupal. Once you've got the legacy data into MySQL, Table Wizard takes care of pretty much everything else for you: it analyses the legacy data and suggests migration paths; it lets you map legacy fields to Drupal fields through a UI; and it can test, perform, and re-perform the actual migration incrementally as a cron task. Very useful tool, especially for these guys, who are now specialising in data migration full-time.
  • I unfortunately missed this one, but Chris Bryant gave the talk "Drupal Patterns — Managing and Automating Site Configurations". Along with Context and Spaces, the Patterns module is getting a lot of buzz as one of the latest-and-greatest tools that's going to change the way we do Drupal. Sounds like Patterns is taking a similar approach to Context and Spaces, except that it's centred around configuration import / export rather than "feature" definitions, and that it uses YAML/XML rather than raw PHP Exportables. I'll have to keep my eye on this one as well.

Come a long way

I have quite a long history with the issue of deployment and migration in Drupal. Back in 2006, I wrote the Import / Export API module, whose purpose was primarily to help in tackling the problem once and for all. Naturally, it didn't tackle anything once and for all. The Import / Export API was an attempt to solve the issue in as general a way as possible. It tried to be a full-blown Data API for Drupal, long before Drupal even had a Data API (in fact, Drupal still doesn't have a proper Data API!). In the original version (for Drupal 4.7), the Schema API wasn't even available.

The Import / Export API works in XML by default (although the engine is pluggable, and CSV is also supported). It bypasses all of Drupal's standard foo_load() and foo_save() functions, and deals directly with the database — which, at the end of the day, has more disadvantages than advantages. It makes an ambitious attempt to deal with non-unique numeric IDs across multiple instances, allowing data items with conflicting IDs to be overwritten, modified, ignored, etc — inevitably, this is an overly complex and rather fragile part of the module. However, when it works, it does allow any data between any two Drupal sites to be merged in any shape or form you could imagine — quite cool, really. It was, at the end of the day, one hell of a learning experience. I'm confident that we've come forward since then, and that the new solutions being worked on are a step ahead of what I fleshed out in my work back in '06.

In my new role as a full-time developer at Digital Eskimo, and particularly in my work on live local, I've been exposed to the ongoing deployment challenge more than ever before. Sacha Chua said in DC that (paraphrased):

"Manually re-doing your database changes through the UI of the production site is currently the most common deployment strategy for Drupal site maintainers."

And, sad as that statement sounds, I can believe it. I feel the pain. We need to sort out this problem once and for all. We need a clearer separation between content and configuration in Drupal, and site developers need to be able to easily define where to draw that line on a per-site basis. We need a proper Data API so that we really can easily and consistently migrate any data, managed by any old module, between Drupal instances. And we need more globally unique IDs for Drupal data entities, to avoid the nightmare of merging data where non-unique numeric IDs are in conflict. When all of that happens, we can start to build some deployment tools for Drupal that seriously rock.

Mar 18 2009
Mar 18

Separate Security Announcements by Type

To make the impact of different security advisories and announcements easier to see, they are now separated by type.

Drupal core security advisories: http://drupal.org/security
RSS feed for Drupal core: http://drupal.org/security/rss.xml

Contributed project security advisories: http://drupal.org/security/contrib
RSS feed for contributed projects: http://drupal.org/security/contrib/rss.xml

Public service announcements: http://drupal.org/security/psa
RSS feed for announcements: http://drupal.org/security/psa/rss.xml

We encourage those using RSS readers to track security-related developments to subscribe to all three of these feeds.

All posts to each of these three forums will still be sent to the one security announcements e-mail list. To subscribe to that e-mail list, once logged in, go to your user profile page and subscribe to the security newsletter on the Edit » My newsletters tab.

All future public service announcements will only be posted to the Public service announcements page and feed.

Background on the Changes

At Drupalcon in Washington, D.C. earlier this month, members of the Security team held a "Birds of a Feather" session to discusses various topics including improvements to our process of communicating with the public.

One outcome of this meeting was that we decided to more clearly differentiate among security advisories for Drupal core (which affect all users) as opposed to security advisories for contributed projects (which are often used by only tens of sites). In addition, the security team has on occasion issued announcements (such as this one), which were previously mixed in with actual security advisories.

Since the Drupal 6.x upgrade of http://drupal.org, newsletter postings have been managed using forums. The security team has thus split security-related postings among three forums under http://drupal.org/forum/1188.

All past and new advisories and announcements and their feeds can be viewed (via tabs) on http://drupal.org/security.


The security team for Drupal can be reached at security at drupal.org or via the form at http://drupal.org/contact.


About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web