Apr 09 2009
Apr 09

Open Source Micro-Blogging CMS Software & Twitter Integrations

Posted by Jeffrey Scott -TypeHost Web Development | Thursday, April 9th, 2009
, ,

With all of the news about a possible Twitter sale to Google, I am wondering if we will see an increased trend in clients looking for micro-blogging sites and “Twitter Clones” for local and niche communication. Already, I am offering Twitter and Social Network integration (Facebook, mySpace) to clients on blog and ecommerce sites, to easily connect with friends, community, marketing, communication, etc. that takes place on those sites from the main domain. More and more people are including their Facebook status messages and Twitter stream on their homepages, using the API & RSS feeds those sites offer to pull social content across network channels.

WordPress Plugins:

Xavisys, the web development company behind WebDevNews.net, has created a Twitter feed module for WordPress called WordPress Twitter Widget Pro.

Drupal Modules:
For Drupal, I find the best module to be Activity Stream.

This module will republish all of your “tweets” into your Drupal site, as well as building a stream from your Facebook, Digg, Delicious, and other social networking and bookmarking sites. Highly recommended.

Also very promising for Drupal, but still in development, is the Facebook Status module (Facebook-style Statuses).

As expected, this module replicates the Facebook “Wall” and allows users to post status messages on their user profile pages. When I tried the module previously, there were still some bugs that would have prevented its use on a live site, but huge potential here with this module and a 2.0 version is now released.

The Twitter module allows users to:

  1. Associate one of more Twitter accounts with their Drupal user account
  2. Have their tweets displayed in a sidebar block or on their user profile
  3. Post to their own Twitter account or a site-wide Twitter account whenever they create new content


The Tapatio Projects seeks to build an installation profile for Drupal that “enable(s) users to leverage a drupal system as a front end to twitter.com (and other sources in the future) allowing them to use drupal as a hub for message aggregation, moderation, and dispatching.”



Stan alone CMS Software:

If you are interested in breaking out from a CMS like Drupal or WordPress and building a site that is a stand alone micro-blogging platform like Twitter, the Laconica open source software may be of interest.

For an example of a Laconica site, see: http://identi.ca/

The alternative to Laconica (but operating on the same open source micro-blogging standard) is Open Microblogger

By design, the open-source micro-blogging sites share an API to allow easy cross posting and searching of messages between sites. They also have more advanced built in SMS capabilities, something you will have to add extra modules for in Drupal & WordPress.

Whether your client is requesting Twitter integration into their home page or business site, or you have a request to build a full micro-blogging platform, one of these solutions should make a good base to build upon.


Apr 09 2009
Apr 09

Since the Summer of Code of Version Control API's inception ended, there had always been one piece of cvs.module functionality that hadn't yet been ported to the new VCS-independent infrastructure. Incidentally, this was also one of the most visible and important features on drupal.org: packaging releases from CVS tags and branches by means of a simple two-step form.

Well, not anymore! Yesterday, I released Version Control API 6.x-1.0-rc1, which sports a number of important improvements under the hood, and versioncontrol_project 6.x-1.0-rc1, which makes use of these new features to provide release node integration and a release tarball packaging script, like the one found on drupal.org. The main difference is that the code is not CVS specific, and even though only the CVS backend supports the required functionality at the moment there is nothing holding up an implementation for SVN or the newly-revamped Git backend.

The latter has pretty much singe-handedly been ported by new contributor CorniI (a.k.a. Cornelius R.) to Drupal 6 and to API changes in Version Control API for 6.x-1.x. He's not yet done making sure that everything works as intended, but most importantly the Git backend runs again and can be played with. Good times coming for DVCS support!

So with Version Control API & friends being "feature-complete", the next step is to push it onto drupal.org and replace cvs.module. For that to happen, the primary task is to complete the migration scripts that pull data from cvs.module to Version Control API, If you want to help out with that, you can get in contact with me, dww and hunmonk - unless new cvs.module functionality is added in the meantime, the data migration is the last missing piece for getting deployed on drupal.org.

In general, the roadmap for Version Control API looks like this:

  • Make the 6.x-1.x releases suitable for drupal.org, running on CVS only (like d.o does today). This is important so that improvements get contributed to Version Control API instead of cvs.module, which avoids porting more dozens of newly contributed features.
  • Changes that make it possible to run drupal.org on other version control systems will go into a 6.x-2.x branch. That includes user authentication changes to enable SSH key or HTTP(s) authentication, and important non-CVS log parsing performance improvements that can be achieved by making the API object-oriented, and stuff that makes distributed version control systems work more nicely with Version Control API.

Hope to see you contributing soon!

Apr 09 2009
Apr 09

The evening of April 8th 2009 saw the second Ignite Cardiff event, which was organized by Cardiff Web Scene and Nocci. I had foolishly put my name forward to do a talk, and obviously did it about Drupal.

In the talk, which you can see below, I quickly ran through what Drupal is, and how to build a simple web site. I showed the making of a fictional jobs sites, http://jobs.timmillwood.com/.

Apr 09 2009
Apr 09

Something odd happened to me today. I ran into a complete stranger on the Internet.

I signed into chat, and almost immediately had the conversation below with someone I didn't know, going by the handle "toweringcoho". I was at a largish gathering and had bonjour turned on as usual, so assumed it was someone in the room—even though I didn't bother to look to see what chat connection toweringcoho was using.

A quick Google search suggested that "toweringcoho" is the name of one of a series of IM bots that randomly connect to otherwise unconnected chat users.

And that's how I met Sunil Khiatani from Hong Kong. It took a while for both of us to figure out that we were NOT talking to robots, and a bit longer to introduce ourselves. In the end, we had a worthy conversation, got to know each other a bit, and went on our ways.

I'm not sure if these IM bots are supposed to be malicious, but I liked what happened. It was like going on a kind of unintentional dérive in text only.

6:45:55 PM toweringcoho: Hi, Billy Mays here with another fantastic coho.
6:46:40 PM Nate Angell: wish I knew what that meant...
6:46:52 PM toweringcoho: hmmm
6:46:59 PM toweringcoho: take a wild guess
6:47:04 PM Nate Angell: salmon?
6:47:23 PM toweringcoho: you definitely aren't turing complete
6:47:39 PM Nate Angell: human error
6:48:06 PM toweringcoho: are you related to skynet?
6:48:51 PM Nate Angell: maybe on the distaff side
6:49:14 PM toweringcoho: ahh
6:50:01 PM toweringcoho: here's the thing though, will skynet be porgrammed with the 3 robot laws and if so would it still be able to nuke us?
6:50:28 PM Nate Angell: did the 3 robot laws really work out? have to refer to the text
6:50:54 PM toweringcoho: dunno about the text, but in the movies they didn't
6:51:55 PM Nate Angell: isn't the book always better than the movie?
6:52:21 PM toweringcoho: naw
6:52:28 PM toweringcoho: fight club is better movie wise :D
6:53:22 PM Nate Angell: didn't read fight club
6:55:24 PM toweringcoho: so who are you? :P
6:55:41 PM Nate Angell: @xolotl
6:55:56 PM toweringcoho: huh?
6:56:11 PM Nate Angell: you definitely aren't turing complete
6:56:30 PM toweringcoho: yeah yeah
6:56:57 PM Nate Angell: that should be enough to go on
6:57:20 PM toweringcoho: naw it isn't
6:57:45 PM Nate Angell: there's this thing called google...
6:58:15 PM toweringcoho: nad what should I be searching for
7:01:19 PM Nate Angell: @xolotl
7:01:34 PM Nate Angell: it's a pretty unique character string
7:02:31 PM toweringcoho: you're nate angel?
7:03:23 PM Nate Angell: no, I'm Nate Angell
7:04:05 PM toweringcoho: ah close enough
7:04:08 PM Nate Angell: or, perhaps A dog-like deity, Double of Quetzalcoatl
7:04:10 PM toweringcoho: how come you're contacting me :P
7:04:25 PM Nate Angell: you contacted me
7:04:48 PM toweringcoho: I did???
7:05:10 PM Nate Angell: I think there's an AIM chat robot that connects random users
7:05:14 PM Nate Angell: and we are victims
7:05:30 PM toweringcoho: ahhh
7:05:36 PM toweringcoho: strange
7:05:58 PM toweringcoho: thi is my yahoo account though
7:07:41 PM Nate Angell: i think they are all connected
7:07:52 PM Nate Angell: so you know me, want to iintroduce your self?
7:08:16 PM toweringcoho: alright
7:08:27 PM toweringcoho: I'm Sunil Khiatani, I'm a coder in Hong Kong :D
7:08:37 PM Nate Angell: very cool
7:08:40 PM Nate Angell: what do you code?
7:08:56 PM Nate Angell: Sunil Khiatani doesn't sound very HK ;)
7:09:21 PM toweringcoho: at the moment, stuff for work. Web Services in ASP.NET and C# :\
7:09:30 PM Nate Angell: sorry
7:09:33 PM toweringcoho: been trying to do OSS coding but I've been lazy
7:09:41 PM Nate Angell: that would be better!
7:09:53 PM Nate Angell: as you may have learned, I'm a bit of an OSS zealot
7:10:22 PM toweringcoho: haha yeah a lot of people freak out when I tell them that I'm an indian born in Hong Kong that has a fairly american accent
7:10:31 PM toweringcoho: yeah I think I did, what do you code ?
7:10:34 PM Nate Angell: i guess HK has all types
7:10:36 PM toweringcoho: bbs.. loo
7:10:50 PM Nate Angell: I'm not much of a coder
7:11:13 PM Nate Angell: but I usually evangelize around http://sakaiproject.org http://drupal.org and http://openid.net
7:11:35 PM Nate Angell: there are many worthy projects, depending on your interests
7:11:50 PM Nate Angell: I encourage you to broaden your skills/interests with OSS
7:16:25 PM toweringcoho: I have a few interests
7:16:46 PM toweringcoho: but i think I should focus on the KDE desktop, it's waht i like and use the most
7:19:26 PM Nate Angell: that's a worthy project

Apr 08 2009
Apr 08

There's a big demand from the Drupal community to add fivestar-like ratings to the contrib modules. This would be a pretty cool feature, but it has other concerns too.

In a paper presented in WWW'04 conference titled "Shilling recommender systems for fun and profit" (PDF), the researchers talked about different ways and examples of gaming recommender systems. Such things could happen because the hackers what to 1) promote certain items, 2) "nuke" certain items, and 3) disrupt the entire systems. The researchers also simulated 2 kinds of automatic attacks, NormalBot and AverageBot, and showed that recommender systems are indeed vulnerable to such manipulation attacks.

Apart from academic research literature, it's easy to imagine possible manipulation on Drupal module ratings, either for fun or for profit. New modules are especially vulnerable because a few initial false negative ratings could very likely prevent further evaluations. In fact, if you search "rating manipulation" in Google, you'll find eBay, imdb, Amazon, etc are all victims. And I heard the module rating system in Joomla suffered the same thing too.

To cope with this issue, we need more sophisticated algorithms. My advisor, Paul Resnick, is one of the leading researchers in this area. He and Prof. Rahul Sami published a paper proposing a manipulation-resistance algorithm (PDF. However, a simpler and more intuitive alternative might be to maintain two rating scores -- one from all users, one from the experts. And the experts could be defined as users who registered for more than 1 year and submitted issues, etc.

To sum up, in this blog I'm trying to argue:

  1. Module rating system for drupal.org would be helpful,
  2. But the concern of gaming the system is real and legitmate
  3. Measurements should be taken if the rating system is deployed.

My summer funding would probably come from an NSF research grant on manipulation-resistant algorithms. I'll try to make some proposals on how to prevent gaming the module rating system, if d.o. infrastructure team decides to implement it, after I read more papers in the area.

Apr 08 2009
Apr 08

I've recently been spending more time getting Drupal sites served to survive the storm. We've had a site running the multiple apache mirrors trick using Boost and now a few sites using Varnish as a specialised reverse proxy.

There's some great work going on for Drupal 7 to make it more cache friendly. Looking at not actually starting sessions till they are needed, and adding appropriate headers for example. There are several issue to take into account here. For example Drupal is going to serve some content in different languages with the same URL, even if in the future it may only be the front page. It also will serve content to authorised, logged in users, as well as anonymous users on the same URL. Even if we cache cleverly we need to make sure that any other caches on the way do so too, or don't cache.

Varnish is quite nice for this as you can write pretty complicated rules for caching very simply in its vcl syntax. What I've here is just a start for what could be done, especially when Drupal is more cache aware. For now I'm just correcting some of the things that in the future will be done by core.

'Static' files

Drupal sends lots of files that can be cached and they could have headers so that they aren't rerequested - or if they are they can recieve a 304 not modified response rather than the file. Which these are will depend on your site set up, with different content changing for logged in users, or if you have messages displayed to who aren't logged in. Anything in your /sites directory (css, javascript), and depending where you put them, uploaded files are really promising candidates for general caching. In varnish this can be as simple as:-   sub vcl_recv {
    if (req.request == "GET" && req.url ~ "^/sites/") {
      /* we only ever want to deal with GET requests, we are working
      /* on the assumption that everything in sites is served the same
      /* to all users so we don't want the cookie */

      unset req.http.cookie;

  sub vcl_fetch {
    if (req.request == "GET" && req.url ~ "^/sites/") {
      /* we can unset the Cookie Drupal adds, set a lifetime for the object
      /* and make it cacheable */

      unset obj.http.Set-Cookie;
      set obj.cacheable = true;
      # we can set how long Varnish will keep the object here, or later
      # set obj.ttl = 30m;
      # debug add this and you'll see it in the headers if we came here
      # set obj.http.X-Drupal-Varnish-Debug = "1";
    if (obj.cacheable) {
      /* Things common to all cacheable objects, here it removes
      /* the Expires that are often in the past, sets cache control
      /* and how long varnish will keep it
      /* and mark it for delivery (and storing) */

      unset obj.http.expires;
      set obj.http.cache-control = "max-age = 900";
      set obj.ttl = 1w;
      set obj.http.magicmarker = "1";

  sub vcl_deliver {
    if (resp.http.magicmarker) {
      /* unset marker and serve it for upstream as new */
      unset resp.http.magicmarker;
      set resp.http.age = "0";

As I put my files in /files, and as files links that want storing often have a languge code before them I use another if block elsif (req.request == "GET") && req.url (^/[a-zA-Z]{2})?/files/"), and can use this to set alternative cache times on them. This could also help with the load created by the private file method, using the trick below for knowing which files can be seen by anonymous users and allowing them to have modified cacheable headers, thus reducing the number of times php has to serve files that can be seen to anonymous users.

Caching anonymous page views

In addition to the language and automatic session cookie issues mentioned above our cache doesn't know if users are logged in. We want to cache the anonymous page views (at least those that won't have drupal_set_messages, or other individual changing content, on them). Boost does this neatly by setting it's own cookie when users log in, and unsetting it when logged out. I've used this along side Boost checking for the req.http.Cookie !~ "DRUPAL_UID" and also pinched the code and made a very simple Varinish helper module. So adding some caching for these pages.   sub vcl_recv {
    elsif (req.request == "GET" && req.http.Cookie !~ "DRUPAL_VARNISH") {
      /* this site has drupal_set_messages and importantly changing content
      /* for anon users only on  /user page */

      /* It was tempting to unset.http.cookie; here but it's needed to
      /* stop users who log out getting the last page they saw logged in */


  sub vcl_fetch {
    elsif (req.request == "GET" && req.http.cookie ~! "DRUPAL_VARNISH") {
      if (req.url !~ "(/[a-zA-Z]{2})?/user" && req.url !~ "(/[a-zA-Z]{2})?/admin") {
        /* We don't want the ttl so long on these pages, so we must set
        /* it in the different if blocks rather than cacheable here */

        set obj.ttl = 30m;
        unset obj.http.Set-Cookie;
        if (req.url !~ "^[a-zA-Z]{2}/") {
          /* make sure that language is taken into account on caching pages
          /* without a langage code in the url, and make sure that caches
          /* know if there is a cookie with the page it's not to use the
          /* cached one */

          set obj.http.Vary = "Accept-Language, Cookie";
        else {
          set obj.http.Vary = "Cookie";

Older versions of Varnish

Varnish comes out of EPEL for RHEL/CentOS, and is pretty up todate. I've done this also with a Debian stable box and as the version of Varnish is older the supported syntax for vcl is a bit more limited. You can't change the obj.cacheable boolean for example so I used an obj.http.value that I then unset. The comparitive (a !~ b) was causing errors, when (! a ~ b) didn't. The command deliver is called insert, and unset is remove.

Apr 08 2009
Apr 08

created on Tue, 2009-04-07 16:37

In November of 2007, Raincity Studios struck a deal to acquire, Bryght, the pioneering Drupal hosting solutions company. By combining the Raincity Studios development and design team with the hosting expertise of the folks at Bryght, we hoped to provide comprehensive online solutions to a range of clients. The last year and half has been a great learning experience, however it is with regret that today we must announce that effective April 30th, 2009 Bryght hosted services will be phased out with a plan to be closed completely by May 29, 2009.

Over the past five years, Bryght and Raincity Studios have forged many wonderful and productive relationships with partners and clients around the world. We pride ourselves in being able to create mutually beneficial partnerships.  As two companies that emerged at the same time and grew up together in Vancouver, we have had no relationship more meaningful than that with Bryght. The shared vision and complementary personalities of the two companies made for a excellent fit and we believe the cooperative efforts produced great results. 

Bryght ideas, ahead of their time

Bryght was an early player in helping to build the Web 2.0 industry and one of the first group of people to put Drupal publishing tools in the hands of the untrained public (a scary prospect at the time).  As the first commercial venture in the Drupal world, Bryght paved the way for all sorts of individuals who earn a living today using Drupal.  As early innovators and active contributors to the Drupal community, the team at Bryght worked tirelessly to develop the Hostmaster module and Aegir hosting system giving site administrators tools to help manage multiple sites and rapidly deploy new site installations.  Their services, Bryght VPS and Bryght Light, released in 2005 were the first hosted Drupal offerings and made signing up for a turn-key Drupal website simple and effortless for the end user.

Over the past year as we worked to improve our offering by relaunching Bryght.com, and adding new languages (French and Chinese), and upgrading our servers and technology, it became apparent to us that in order to offer competitive pricing and the best possible service to our clients, hosting must be carried out on a scale that is beyond our current capacity and in turn we could not provide you with the level of service that we would expect from anyone else.  

In the midst of an economic downturn we recognize the importance of keeping our company agile and innovative.  At the moment, we want to focus on doing what we're best at: developing and delivering innovative applications and software solutions to power online communities. 

Adrian Rossouw, the architect and father of Aegir, is now part of the great team at developmentseed.org. Together they are committed to continue the effort that he and Bryght put forth over the years. Combined with their internal projects, Context and Spaces, we feel this is a great use of Adrian's talents and opens new options to the technology we helped develop.

We also want to wish the best to our "coopetitors" in the hosting market, especially those offering turn-key hosted Drupal solutions, such as Acquia Gardens and Fields, Lullabot (with their forthcoming and still unnamed entry into the market) and Work Habit’s Elastic2. We recognize that the continued success of these companies is good for everyone in the community and industry.

Existing Bryght Customers

For our existing Bryght Light and Bryght VPS customers, we thank-you for your business and want you to know that we are committed to making sure your transition to a new hosting provider will be as smooth and painless as possible.  We've partnered with hosting providers Rackspace and Slicehost and will be able to offer you competitive affiliate pricing as well as facilitate the migration of your site to its new home.  Depending on the traffic your site is receiving, we can find the best solution for your needs.  As a Bryght customer, you will receive more information by email today. 

If you have any questions at all, please contact us at [email protected]


Apr 07 2009
Apr 07

As the SVP of Global Operations, Sherborne’s key mandate is to make Appnovation a Global Growth Company. Sherborne has a lengthy track record of successful project delivery in both software development and operations. 

His past experience includes managing large-scale web development projects for clients such as Best Buy and EA. Sherborne has helped shape and led organizations such as UBC, Blast Radius, Nokia, and EA. Prior to joining Appnovation, he led a high-performance operations and consulting team with DV8 Interactive in Vancouver. 

Sherborne's career in the IT industry began 15 years ago as a Computer Analyst for Budget Rental Car on their Y2K project.  His interest in IT combined with a Bachelor of Technology degree from BCIT, has led Sherborne into the realm of project management and technology leadership.

Weekends are Spent: Tinkering on his car or at the beach

Bucket List Accomplishments: Traveling to Europe

Favourite Book: Dr. Seuss – a classic for everyone!

Apr 07 2009
Apr 07

Just a few short months on and I'm back from yet another awesome Drupal Camp Ireland. Over 60 people attended having traveled from all around the country, and even from further afield such as Scotland, England and the U.S. The camp ran over two days and included many presentations from building a simple site to writing secure code to documentation. Not only that, but the Irish Drupal community also built brand new websites for three non-profits in Ireland, Zikomo, Rural Science Association and Shadowbox Theatre Company.

On the Saturday, we held two day-long tracks of presentations, one for newbies and one for more advanced users. Leon Butler kicked off the newbie track with a presentation on his site galwayflux.com. This was particularly interesting as Leon is relatively new to Drupal and was able to show how easy it was for him to put together a site with no coding and just some basic HTML knowledge.

Then came the "hard-stuff" :) I did a live demonstration on how to build a simple site, which contained a blog, contact form and a handful of static pages. I then followed it up with another presentation on CCK and Views which resulted in the site gaining an image gallery, complete with Lightbox2. This was done for Shadowbox Theatre Company which is a small non-profit who lost their funding earlier this year. They work with both the elderly and groups of people living with mental and intellectual disabilities through theatre.

We were also honoured to have Lullabot's very own Addison Berry (add1sun) in attendance. She did an excellent presentation, "Documentation is hot!", which really encouraged our new Drupal users to get involved in the community. She then did a similar presentation in the advanced track, as well as talking about usability. We were really delighted that she was able to come, and hope that she can come back to our next one! :)

For the advanced track, we went for the unconference approach. This didn't work as well as we hoped as there were a lot of requested topics but not enough "experts" to cover them. However, we did have some interesting presentations on security, RDF and Drupal 7. In retrospect, we should also have added an intermediate track, as there were some people who knew the basics, but weren't quite ready for the advanced track. Hopefully we can add this next time round.

Sunday saw us split into two teams, led by myself and Alan Burke, for the site-building challenge. Two months ago we invited Irish charities and non-profits to apply for a free Drupal website. The response was amazing. We had almost 50 applications, all from very worthy organisations, which made it quite a difficult decision to make. In the end we decided on Zikomo, which is a charity group committed to fostering long-term self-sufficiency in southern Malawi, and Rural Science Association, who work in the area of rural development.

Both organisations worked with us, adding content, uploading images and so on. The sprint lasted just over 6 hours and at the end we had two great sites. After some difficult deliberations, and only a two point difference out of a total of 100, the Zikomo team were deemed the winners. However both teams received prizes, from Drupal books to t-shirts to Flickr Pro accounts. A number of companies sponsored the prizes, including Lullabot, Packt, Connemarathon and DFSA. We also gave all three of the non-profit organisations a year's free hosting in addition to their new websites.

While the site-building challenge was happening, Addison ran a documentation sprint. A number of new Drupal users worked with her, which was great as they were able to provide an outsider's perspective. They went through the Getting Started handbook and the Drupal Cookbook, identifying areas needing clarification and fixing, and giving Addison lots of useful feedback.

Thanks to our sponsors, we were able to hold the event free of charge. The DERI Institute in Galway provided us with a free venue and IO1 supplied lunch on both days.

At DrupalcCn Szeged, Stéphane Corlosquet, Alan Burke, Heather James and myself decided that we wanted to raise the profile of Drupal within Ireland, and since then we've done just that. In the past 6 months, we've had two Drupal Camps, the first of which saw a 5 fold increase in the number of people attending. We've started organising local monthly Drupal meetups, and have seen a massive increase, both in terms of members and activity, in the Ireland Drupal group on groups.drupal.org. Here's hoping we can keep up the momentum!

We're all delighted with the success of our latest Drupal Camp, and have even started planning the next one! All going well, the next event will be held in Belfast in October later this year, with Stephen Gray and Feargal O'Kane heading up the organisational team. I'm sure it'll be another fantastic event and I, for one, can't wait!

Apr 07 2009
Apr 07

I recently had to write a multi-step form in Drupal 6. Of course, I turned to documentation to see how others are doing it. Pro Drupal Development offers the basics, so do the 5 to 6 upgrade notes, and others. I felt that many approaches suffered from design flaws that made the code cumbersome to manage beyond a couple steps. I set out to develop a multi-step form method with the following goals:

  • One form builder with nested conditional statements is difficult to manage, each step should be its own form array function
  • Steps shouldn't be numbered, e.g. to move to the next step don't $form_state['storage']['step']++
  • Each step should be able to have its own validate and submit handlers
  • Steps should be form alterable

As far as Form API knows, there is one form builder and thus one validation and submit function. The key is, each piece (builder, validate, and submit function) directs to sub-functions that perform during the appropriate step. Value elements are heavily used to control flow by informing the system what the next step is and for handling step validation and submit.

If you're not too familiar with Drupal's Form API watch this excellent intro video from my friend Chris Shattuck at BuildAModule.com

Let's look at some pseudo-code to explain the main idea of what I'm doing.

We get started with drupal_get_form('main_builder')

function main_builder(form_array) {
  Check if we've set our next step
  If we have call that step's function and
  return it's Form array
  If we don't have a step than we're at the
  beginning of our form
  Call and return first_step()

function first_step(form_array) {
  Build the form elements we want the user to enter

  Define what the next step from this one is
  form_array['next_step'] = 'a_single_step';
  return form_array;

function a_single_step(form_array) {
  Build the form elements we want the user to enter
  Define what the next step from this one is
  form_array['next_step'] = 'next_step';

  return form_array;

function main_builder_submit(form_array) {
  Store submitted form values

  Set next step

The advantage here is each step knows the next step and each step is contained within its own function, allowing for easy modification. The main form builder function dispatches to each individual step to build its own form array. The form submit handler stores submitted values in form storage per usual.

Let's look at some Drupal code now.

// We call drupal_get_form('multistep_form')
// elsewhere, such as an implementation of hook_menu().
function multistepform_form($form_state) {
  if (!empty(
$form_state['storage']['step'])) {
$function = $form_state['storage']['step'];
  else {


_multistepform_form_start() {
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#required' => TRUE,


$form['continue'] = array(
'#type' => 'submit',
'#value' => 'Continue',
// Our special value elements.
$form['this_step'] = array(
'#type' => 'value',
'#value' => 'start',
$form['step_next'] = array(
'#type' => 'value',
'#value' => '_multistepform_form_food',


_multistepform_form_food($form_state) {
$form['food'] = array(
'#type' => 'textfield',
'#title' => t('Food'),
'#required' => TRUE,
$form['continue'] = array(
'#type' => 'submit',
'#value' => 'Continue',
$form['this_step'] = array(
'#type' => 'value',
'#value' => 'food',


multistepform_form_submit($form, &$form_state) {
  if (empty(
$form_state['storage'])) {
$form_state['storage'] = array();
$form_state['storage']['values'] = array();
// Store submitted form values
$this_step = $form_state['values']['this_step'];
$form_state['storage']['values'][$this_step] = $form_state['values'];


// Set up next step.


if (!empty($form_state['values']['step_next'])) {
$form_state['storage']['step'] = $form_state['values']['step_next'];
  else {
// Form complete!

See the full example in the attachment

As you can see, this method uses special form value elements to define the flow. The main builder uses variable functions to delegate which step it is. The second step, _multistepform_form_food() does not set a 'step_next' value and so on submission we don't set a step that will be called when we return to the main builder. I use the 'this_step' value to namespace submitted values in form storage. Other than displaying the message "Complete!" I am not actually doing anything with the final, collected values yet.

The same delegation method using variable functions that the main form builder does can be applied to validate and submit handlers by creating value elements 'step_validate' and 'step_submit' with function names as the value in step form builders and the following main validate and submit addition:

function multistepform_form_validate($form, &$form_state) {
  if (!empty(
$form_state['values']['step_validate'])) {
$function = $form_state['values']['step_validate'];
$function($form, $form_state);

And this code in multistepform_form_submit().

if (!empty($form_state['values']['step_submit'])) {
$function = $form_state['values']['step_submit'];
$function($form, $form_state);

Custom validation functions can form_set_error() normally. By specifying a step submit, our submit function can alter the form flow, skipping steps.

function _multistepform_form_like_music($form_state) {
$form['like_music'] = array(
'#type' => 'radios',
'#title' => t('Do you like music?'),
'#options' => array(
0 => 'No',
1 => 'Yes',
'#required' => TRUE,
$form['continue'] = array(
'#type' => 'submit',
'#value' => 'Continue',
$form['this_step'] = array(
'#type' => 'value',
'#value' => 'like_music',
// New value, 'step_submit'.
$form['step_submit'] = array(
'#type' => 'value',
'#value' => '_multistepform_form_my_submit',
$form['step_next'] = array(
'#type' => 'value',
'#value' => '_multistepform_form_music',


_multistepform_form_my_submit($form, &$form_state) {
  if (
$form_state['values']['like_music'] == '0') {
// If the user doesn't like music, well don't ask them anything more about it!
$form_state['values']['step_next'] = '_multistepform_form_final';

In this example if the user says (s)he doesn't like music (Who would choose that, really?) then instead of seeing the step _multistepform_form_music() (s)he gets sent to _multistepform_form_final().

I touched on the 'this_step' value element earlier, but it plays the part of identifying individual steps, allowing each step to be form alterable. Your implementation of hook_form_alter() could look for the multi-step form_id and if $form['this_step'] matches what you're looking for. hook_form() may offer a solution, but I'm not certain it's better or easier than using an additional value element.

After developing this method I was informed it is like Chaos tool suite's wizard. Other multi-step form approaches exist such as Pageroute, an object-based approach to steps of a flow.

The important pieces to use are variable functions and passing the $form_state array around by reference. For further exploration on this method I plan to see if it could be used to move backwards in a form, returning to previous steps. And the special value elements here are just a convention but I could see them being defined by hook_element().

Take a look at the attached .module for a full example spanning more than two steps. The code implements custom validation and a custom submit handler to alter form flow. If you would like to demo the code you'll need a multistepform.info file. Further directions for module development is in the Drupal handbooks.

Update 07/11/2011 The Examples module for Drupal provides multi-step form directions and is a great resource

Apr 07 2009
Apr 07

7 Apr 2009

Posted by jpotts

UPDATE: Screencast now lives here:


I’ve created a new screencast that shows the Alfresco-Drupal CMIS integration in action over at Optaros Labs. The screencast shows content moving back-and-forth between Alfresco and Drupal, content being displayed in a Drupal site that lives in Alfresco, and a CMIS CQL query being executed against the Alfresco repository from Drupal.

The Drupal CMIS module and the CMIS Alfresco module are available at Drupal.org.

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



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