Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Apr 20 2009
Apr 20

People often need to build a custom user interface on top of the Alfresco repository and I see a lot of people asking general questions about how to do it. There are lots of options to consider. Here are four options for creating a user interface on top of Alfresco, at a high level:

Option 1: Use your favorite programming language and/or framework to talk to Alfresco via REST or Web Services. PHP? Python? Java? Flex? Whatever, it’s up to you. The REST API is nice because if you can’t find a URL that does what you need it to out-of-the-box, you can always roll-your-own with the web script framework. This option offers the most flexibility and creative freedom, but of course you might end up building constructs or components that you may have gotten “for free” from a higher-level framework. Optaros‘ streamlined web client, DoCASU, built on Ext-JS, is one freely-available example of a custom UI on top of Alfresco but there are others.

Option 2: Use Alfresco’s Surf framework. Alfresco’s Surf framework is just that–it’s a framework. Don’t confuse it with Alfresco Share which is a team-centric collaboration client built on top of Surf. And, don’t assume that just because a piece of functionality is in Share it is available to you in the lower-level Surf framework. You may have to do some extra work to get some of the cool stuff in Share to work in your pure Surf app. Also realize that Surf is brand new and still maturing. You’ll be quickly disappointed if you hold it to the same standard as a more widely-used, well-established framework like Seam or Django. Surf is a good option for quick, Alfresco-centric solutions, especially if you think you might want to leverage Alfresco’s browser-based site assembly tool, Web Studio, at some point in the future. (See Do-it-yourself Alfresco Surf Code Camp).

Option 3: Customize the Alfresco “Explorer” web client. There are varying degrees to which you can customize the web client. On one end of the spectrum you’ve got Freemarker “presentation templates” followed closely by XML configuration. On the other end of the spectrum you’ve got more elaborate enhancements you can make using JavaServer Faces (JSF). Customizing the Alfresco Explorer web client should only be considered if you can keep your enhancements to an absolute minimum because:

  1. Alfresco is moving away from JSF in favor of Surf-based clients. The Explorer client will continue to be around, but I wouldn’t expect major efforts to be focused on that client going forward.
  2. JSF-based customizations of the web client can be time-consuming and potentially complex, particularly if you are new to JSF.
  3. For most solutions, you’ll get more customer satisfaction bang out of your coding buck by building a purpose-built, eye-catching, UI designed with your specific use cases in mind than you will by starting with the general-purpose web client and extending from there.

Option 4: Use a portal, community, or WCM platform. This includes PHP-based projects like Drupal (Drupal CMIS Screencast) or Joomla as well as Java-based projects like Liferay and JBoss Portal. This is a good option if you have requirements that match up well with the built-in (or easily added-on) capabilities of those platforms.

It’s worth talking about Java portal servers specifically. I think people are struggling a bit to find The Best Way to integrate Alfresco with a portal. Of course there probably is no single approach that will fit every situation but I think Alfresco (with help from the community) could do more to provide best practices.

Here are the options you have when integrating with a portal:

Portal Option 1: Configure Alfresco to be the replacement JSR-170 repository for the portal. This option seems like more trouble than it is worth. If all you need is what you can get out of JSR-170, you might as well use the already-integrated Jackrabbit repository that most open source portals ship with these days unless you have good reasons not to. I’m open to having my mind changed on this one, but it seems like if you want to use Alfresco and a portal, you’ve got bigger plans that are probably going to require custom portlets anyway.

Portal Option 2: Run Alfresco and the portal in the same JVM (post). This is NOT recommended if you need to scale beyond a small departmental solution and, really, I think with the de-coupling of the web script engine we should consider this one deprecated at this point.

Portal Option 3: Run the Alfresco web script engine and the portal in the same JVM. Like the previous option, this gives you the ability to write web scripts that are wrapped in a portlet but it cuts down on the size of the web app significantly and it frees up your portal to scale independently of the Alfresco repository tier. It’s a fast development cycle once you get it set up. But I haven’t seen great instructions for setting it up yet. Alfresco should document this on their wiki if they are going to support this pattern.

Portal Option 4: Write your own portlets that make services calls. This is the “cleanest” approach because it treats Alfresco like any other back-end you might want to integrate with from the portal. You write custom portlets and have them talk to Alfresco via REST or SOAP. You’ll have to decide how you want to handle authentication with Alfresco.

What about CMIS?

CMIS fits under the “Option 1: Use your favorite programming language” and “Portal Option 4: Write your own portlets” categories. You can make CMIS calls to Alfresco using both REST and SOAP from your own custom code, portlet or otherwise. The nice thing about CMIS is that you can use it to abstract the underlying repository so that (in theory) your front-end code will work with different CMIS-compliant back-ends. Just realize that CMIS isn’t a fully-ratified standard yet and although a CMIS implementation is in the Enterprise version of Alfresco, it isn’t clear to me whether or not you’d be supported if you had a problem. (The last response I saw on this specific question was a Peter Monks tweet saying, “I don’t think so”).

The CMIS standard should be approved by the end-of-the-year and if Alfresco’s past performance is an indicator of the future, they’ll be the first to market with a production-ready, fully-supported CMIS implementation based on the final spec.

Pick your poison

Those are the options as I see them. Each one has trade-offs. Some may become more or less attractive over time as languages, frameworks, and the state of the art evolve. Ultimately, you’re going to have to evaluate which one fits your situation the best. You may have a hard time making a decision, but you have to admit that having to choose from several options is a nice problem to have.

Apr 10 2009
Apr 10

Is writing Drupal tests boring? Maybe. Is running tests boring? Not anymore!

There is a patch for Drupal 7 pending that introduces a couple of new hooks into the simpletest module. These hooks will allow you to listen to the progress of a test run and react to tests that pass or fail. I have already created a new testlistener module that uses these new hooks to execute shell commands.

Some examples:

I have a Dell XPS laptop with built-in LEDs that can be controlled using the dellLEDCtl shell command (Linux). Using these new hooks, I can turn the LEDs green at the start of a test run, make them red when a test fails and turn them off when the test run has completed. This is very similar to the functionality of my Eclipse XPS plugin that shows JUnit results in Eclipse.

Another (typical) example is to have two lava lamps, a red one and a green one. You connect both of them to an X10 device (I have an X10 starterkit from IntelliHome) so you can turn them on/off with the heyu shell command (Linux). The testlistener module allows you to let the lamps reflect the status of the Drupal code. Other people are using this setup in their (non-Drupal) continuous integration environment.

If lamps are too soft for you, you might consider shooting missiles instead.

Drupal testing will never be boring again ;)

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(&$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:

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

    </span>$callbacks['notifications/%user_uid_optional/nodetype'] = $callbacks['user/%user/notifications/nodetype'];

    </span>$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.

Mar 05 2009
Mar 05

OpenBand has today unveiled its new OpenBand Labs website to help improve the information around the work we've been doing over recent years as well as hopefully invite some discussion.

OpenBand Labs

We hope to make some improvements to the new site over the coming days as we continue to add some more information and blog about some of our experiences here at DrupalCon. We'll also be adding the slides and some writeups about the XMPP talk Darren gave yesterday and the distributed enterprise talk Ben gave today.

We had a great presentation yesterday with Darren Ferguson talking about the XMPP Framework, and today with Ben Lavender talking getting a chance to demonstrate our collaboration platform.

Mar 03 2009
Mar 03

I'm in Washington, DC this week with many of the rest of the OpenBand / M.C. Dean team. We're all here to visit DrupalCon DC and meet our friends and associates in the Drupal community as well as present some of the things we've been working on.

A couple of the sessions that we proposed have been accepted, so we're going to be presenting:

If you're interested in the work we've been doing to help distributed enterprises communicate better, feel free to come up and say hi. We look forward to meeting you at DrupalCon!

Feb 27 2009
Feb 27

I was working the other night to create an integration module that would tie the existing Activity Stream module for Drupal into the Brightkite location-based social network.

The idea is that users can check in at their current location using Brightkite and have their Drupal site update their location within the site based on their last known location - handy if you want a little map that shows where you are, for example, but you could do whatever you wanted with those locations, and even use them to extend a social network you might be building up in Drupal.

While I was fighting with the SimplePie feed parsing library to work out why it didn't like the feeds from Brightkite, John McKerrell suggested that some integration for his new Mapme.at service would be nice too.

So, the first two services to be supported by the new Activity Stream location services project are Brightkite and Mapme.at. I'd also like to extend this to other services like Yahoo's Fire Eagle and Google Latitude at some point, but neither of them are quite so simple to integrate with, the former because it has no public location feeds for users and requires authentication, and the latter because it doesn't share any of its data at all (boo!).

In their most basic form, the modules pull in the updates from these services and they get included in your activity stream along with your Twitter updates and the like, but also if you have Location module installed and the user locations module enabled (plus a patch for Activity Stream for now), your user will be updated with the latest coordinates from the location service you use.

Jan 22 2009
Jan 22

Ballavayre CottagesThe new website for Ballavayre Cottages went live recently to give a new online presence to this 5 star self-catering accommodation in their 200 year old cottage in Colby, Isle of Man.

The site, built on Drupal, allows the cottage owner to change content as and when they wish, and also to update their availability calendar to let visitors know when the cottages are available.

To help visitors see at a glance where the cottages are located, and to give directions from the sea terminal and airport, we included a series of custom built maps, designed (with some very helpful tips from Steve Chilton) using OpenStreetMap data.

Directions to Ballavayre Cottages

It is always great to help promote the Isle of Man as a tourist destination, even in a small way, by giving accommodation providers a chance to promote their services to a wider market.

Jan 15 2009
Jan 15

Man, we’re getting old!

Today (January 15th) is the 8th anniversary of the day Drupal 1.0 was released. Although Dries had no idea at the time - it was a move that would not only change his life, but mine too…

January 2009 also marks the 5th anniversary of my starting to work on Drupal full time (after a few years of “hobby” involvement). My first project (at the time, actually a re-launch) still stands as one of my favourites: http://www.terminus1525.ca/ . Since then, Drupal has defined my career: from co-founding Bryght to my current life as a Lullabot. The community is home to some of my best friends and people I love.

Five years - full-time. No wonder I feel old.

Jan 10 2009
Jan 10

I'll be attending 2 major conferences the next couple of weeks.

First of all there's FOSDEM in Brussels on February 7th and 8th. I'm particularly interested in the Drupal devroom on Sunday, but there are plenty of other open source sessions throughout the weekend.

The second conference I'll be attending is DrupalCon in Washington from March 4th until 7th. I expect to pick up a couple of tips and tricks about Drupal 6 and I hope to learn a lot about the upcoming changes in Drupal 7. I'm pretty sure that being among that many Drupalistas will help me to find more ways to give something back to the community.

I never attended FOSDEM nor DupalCon (and I haven't been in the US recently) so I'm looking forward to both events!

Jan 07 2009
Jan 07

It's amazing how much spam is generated when commenting is enabled on a blog. When I first launched the Drupal version of dankarran.com, I had commenting enabled for new posts but had it set so that administrator approval was needed before any new comments went live. Coming from a MovableType blog previously, I was used to doing this as I received tons of spam on that blog and had to moderate there as well. It's not a good user experience to expect people to wait until I approve a comment though, so I was keen to let users post directly.

When the site first launched, there were very few spam comments, so leaving comments open seamed feasible, but very soon - as spammers started to pick up on the changes - they started arriving in droves, and that was just on the few comment-enabled posts that I had created since launching.

Not wanting to impede people's commenting with a captcha for every comment, I avoided Drupal's captcha module and instead opted to try out the Mollom module as an interface to the Mollom spam filtering service created by Dries Buytaert, the founder of the Drupal project.

Mollom is a free service that checks all the comments (and/or other forms) posted for known patterns of spam, blocking it where appropriate, and letting real user-created comments through unhindered. If it's not sure whether it's spam or ham (the term for real content), it then presents the user with a captcha that the user can fill in if they have been mistakenly flagged as possible spam.

So far, the service has been great, with 588 spam messages blocked in the past 16 days, the busiest days being Christmas Eve and Christmas Day with 260 spam messages between them. I'm very happy to be a Mollom user! Sorry spammers, it's nothing personal, honest.

Dec 31 2008
Dec 31

From the start of 2009 I am going to be self-employed, and while I will still be working much of my time on the projects I've been working on for the past three years at OpenBand/M.C. Dean, I would also like to start taking on some small Drupal-based projects to go side-by-side with that.

Some of the services I am planning to offer in the New Year include:

  • Drupal site creation
    If you are looking to get a site set up for your small business or organisation, and you like the power that Drupal can give to your site, then I can set a site up for you to meet your needs. I'm particularly interested in creating sites based around geographic information or related to the tourism industry, but I will happily consider any project.
  • Drupal site setup support
    If you need advice on how best to achieve your requirements with existing Drupal modules, I can help point you in the right direction and get you started with your Drupal site setup. This can either be on a remote basis, or on a face-to-face basis in the London area if needed.
  • Drupal module development
    If there isn't already a module in the Drupal community to do what you need, I can help you by building a module to meet your requirements.

If you're interested in taking advantage of these freelance Drupal services for your project, please contact me to discuss your needs.

Dec 15 2008
Dec 15

We needed to disable all of Drupal’s CSS files from our theme. Here’s how we did it:

function THEMENAME_preprocess(&$variables) {

  // Get rid of all of Drupal's CSS files
  $css = drupal_add_css();
  foreach ($css['all']['module'] as $file => $status) {
    if (!strstr($file, 'modules/MYMODULE')) {
  $variables['styles'] = drupal_get_css($css);

We also wanted (no *real* need) to use screen.css rather than style.css, so we edited THEMENAME.info to have this:

stylesheets[all][] = reset.css
stylesheets[all][] = screen.css

… and we removed the line for style.css from it.

Finally, as the superuser we went to /admin/build/modules (or /themes, can’t remember now) to refresh the theme cache. We also had to tick to enable the theme at /admin/build/themes as although we’d been using the theme for ages quite fine, it wasn’t actually ticked before.

And hey presto, it worked. Should probably add that it took waaaay too long to do though, so though we’d add this snipped for others to read.

Share this:

Like this:

Like Loading...
Dec 01 2008
Dec 01

If you build quality sites that attract a large number of visitors and interaction there eventually will come a point when you have to start looking for ways to offload your files and bring down your server overhead. I have been looking into the CDN issue off and on for the past 6 months. Recently I decided it was time to get something dialed in and move forward. I wanted something that required the least number of hacks and was easy and scalable. This post isn't meant to be an end all to Drupal and CDNs, but rather just some insight into the way I have tackled this issue for the time being.

There are a number of options to choose from and a lot of different ways to go about it. You could get a new server locally and load balance your stuff, you could get a new server locally and use it as a static file server, you could team up with a big time CDN like Akamai or Limelight and go that route, or you could go the less expensive CDN route with something like Amazon S3.

Note: This article doesn't attempt to explain every little detail of what's going on, but rather act as a guide for a developer to work off.

My Goals

Being somebody that is cost conscience and wanting to always try to get the most bang for my buck the idea of a CDN like Limelight didn't quite seem like an appropriate fit for me. I wanted something a little bit less serious that I could ease into. I don't care about having servers all across the world and getting content to people a few milliseconds faster than other solutions. I just want to take a huge load off my local network and put that load somewhere else. If my site is up and the users are happy, I'm happy.

I also don't care if 100% of my site files are not offloaded to the CDN. If I can take care of 95% of my load and leave 5% on my main box it really doesn't bother me. My main goal is to get rid of the majority of the overhead and keep everything scalable and dynamic with a relatively small code footprint.

Which files to offload

With these things in mind I have basically decided that a good route for me was to mainly take care of my two main sources of files: images and videos. If I really wanted to get hardcore I could also move my CSS and Javascript, but I don't see this as important as taking care of the major problems first.

Take my site www.gunslot.com for example. If you hit the homepage you will see that there are a lot of thumbnails and image requests. Each page probably has at least 20 image requests, some as much as 50. So I would rather take care of these requests first and then I can worry about the 5 or so CSS and JS requests later if I have to.

And then I have the video content which can be large in filesize and taxing on the server. This also had to go.

Local file system

Another thing to keep in mind is that I don't want to make my CDN act as my local file system. I don't want people to upload straight to this and only have this as my main system, I just see too many errors and bugs going this route. I would rather just have everything work normally and smoothly through the default local structure and just copy stuff over to the CDN, which brings up an important point.

Synching your content

Just how should you copy your content over to the CDN? Big time CDNs like Limelight allow HTTP synchronization (which Ted Serbinski talks about in his article) which basically copies your files over automatically. S3 does not offer this type of functionality so you will need to go another route.

You could simply copy them all at once programatically and call it a day. You could also maybe set up a cron and copy any new files every few minutes. But how do you know which files are new? How do you know which files get updated and which don't? You could run some PHP scripts like a cURL or file_get_contents to check the file's last modified time, but this has some big overhead (I tried). So when is the best time to copy the file and how should you do it? You most likely want to get the file over to the CDN as quick as possible, but at the same time you want to make sure if the user updates the file or something is changed your CDN reflects that.

My S3 Solution

I chose to go with a hybrid type approach. I basically send a file over to the S3 every time it is requested, if it is not already there, or if it is newer than the current file.

I have one main routing function that when called will run through the flowchart below and figure out what path to return for any given file, either:

Local: http://www.domain.com/files/full/path/myfile.jpg


S3: http://s3domain.com/files/full/path/myfile.jpg

So basically my flowchart goes something like:

The Technical

S3 Interfacing

So if any of you have messed with S3 you know that you are going to need a PHP class first to put your stuff there. I found a decent class off their forums and went with that (it requires PEAR, unfortunately). At one point I'll probably change this to something better if I find one, but it gets the job done for now.

Filetype check

This is just a quick little function that basically checks if the filetype is listed in an array of allowed filetypes that I have chosen, like: jpg, jpeg, gif, png, flv, mp3, etc.

If file exists

So this is one of the most important steps that I took to make this possible. Rather than actually checking if the file exists on S3 with one of the S3 class functions (slow) or via something like cURL or file_get_contents (slow) I went with a database table on my own server that keeps track of what is on the S3 server (fast). This table keeps track of every filepath and when it was created and changed on S3. I am able to use the changed timestamp from my table to check it against the local file's timestamp (filemtime) to know when the file needs to be updated on S3.

Queuing the file for S3

Originally I didn't queue the file at all and just tried to put the file to S3 every time it was requested - mistake. It obviously took waaaaaaay to long to render my pages with this overhead so I opted for the queue method. I created another database table that keeps track of every file that needs to be put to S3. Basically every time a file doesn't exist on S3 I return the local path for the time being and add this file to the queue.

Putting to S3

As for putting the file to S3 there are a lot of ways to do this and it probably depends a bit on your situation. You could run a cron or some type of rsync if you really wanted to dial it in, but for the time being I am going for a bit more simpler method. I simply run 1 put operation at the end of each page request by the users. This seems to work really well right now and gets the files uploaded pretty much within seconds of when they are queued. At any time I have less than 20 or so files in the queue, and obviously once most of my files are on S3 this doesn't need to run anymore. I run my put function using hook_exit and I pick 1 file each time and get it over to S3.

Routing the files with Drupal

So once you have all this ready to go how do you actually get Drupal to replace the current local paths with the S3 paths? Well, there are a number of ways to do this. If you want to replace all your images, CSS, logos and all that stuff you can patch common.inc, file.inc and theme.inc (maybe more) to run through your routing function. Since I don't care too much about this stuff I skipped this part and decided just to replace imagecache and my videos (for now).


Imagecache comes with a sweet theme_imagecache function that allows you to simply over-ride it in your template.php. You basically just need to tweak the $imagecache_url to run through your routing function and decide which path to return.


If you are using Imagecache for profile pics or nodes you may need to flush the imagecache when these are updated so that your new file will run through the queue and be uploaded to S3. This can be done via some hook_form_alter or hook_nodeapi calls that run the imagecache_image_flush function.


My videos are done through a custom module so I can't really offer any help here. I just plugged my routing function into it.

So that's it!

As you can see for each file request that is going through the routing function it will always check to make sure the newest file is on S3. If it's not it just pulls the local file for the time being. As soon as the S3 file is ready it will start pulling that one. If you do an update it will pull the new local file until the new S3 file is ready again.

That's basically how I'm doing it right now and it's working really well. My server is thanking me and even with fairly high traffic the S3 costs are very reasonable. If anyone has any feedback or tips on how I could make this better lemme know!

 Filed under: Internet / Tech, Drupal, S3, File Server, CDN
Nov 27 2008
Nov 27

My IMCE plugin for YUI Editor has been included in drupal CVS git and the 6.x-2.33 release. Now I can claim to have code included in an official drupal release, ok it is a small plugin for a contrib module, we all have to start somewhere.

The version included in Drupal only supports YUI 2.5.x as the API has changed in 2.6. I have a new version which supports 2.6.x, but it has a layout bug, so I won’t be submitting it until this bug is fixed. If you can tolerate the visual bug or want to help fix it, grab the lastest version of the IMCE plugin for Drupal’s YUI Editor. Use the same installation instructions as last time.

Feedback welcome.

Nov 23 2008
Nov 23

In this episode: Drupal Docs and Drupal Dojo steal all the headlines.

Nov 20 2008
Nov 20

The front-end database is powered by tha Drrupal. Includes a video demonstration.

Nov 16 2008
Nov 16

In this episode: KDI applications on hold, new theme coming for core, installation insurrection, events, site launches.

Links from the episode

KDI Apps on hold until DrupalCon DC

CHX Installation Insurrection

Albin: New theme headed for the core


  • Drupal Showcase:
  • Pregnancy.org
  • SpreadThunderbird.com


Share | Download
Nov 14 2008
Nov 14

This is the podcast for November 14th, 2008. Welcome to the DrupalNews podcast. My goal with this podcast is to provide a quick overview of the most important changes in the drupal community. Story ideas are welcome and encouraged.

Share | Download
Oct 22 2008
Oct 22

Update: This has now been included in the 6.x-2.33 release of Drupal’s YUI Editor module and I have added support for YUI 2.6.

Earlier today I finished off another Drupal based site. The client was pretty happy with it. Once they launch I will probably post a link.

The client came back to me and asked how they could insert images using the rich text editor. Based on some positive reviews I used the YUI Editor module this time around, instead of FCKEditor or tinyMCE for the rich text editor. The YUI Editor module doesn’t support file browsing. I tried to see if someone had already hacked something together for this, if they had I couldn’t find it.

In the past I have used the IMCE module for image browsing and uploading in FCKEditor or tinyMCE. Adding IMCE support to the YUI Editor module seemed like the fastest solution.

So here it is - the IMCE based image browser plugin for YUI Editor on Drupal 6.

Here is a quick howto. Install the YUI Editor and IMCE modules into your Drupal 6 install. Save the plugin tarball into your modules directory above the YUI Editor module and extract it. You should now have 2 extra files yui_editor/plugins called img_browser.inc and img_browser.js

Feel free to leave comments about how well this works for you. Enjoy!

Oct 16 2008
Oct 16

Google has just started testing a new service to inform webmasters that their CMS is vulnerable to security exploits. Currently they are only targetting administrators of sites running WordPress 2.1.1 but my guess is that they'll be adding support for other versions and other platforms in the future.

I hope that they'll be adding support for Drupal as well because it doesn't matter how many security issues the Drupal security team fixes, webmasters still need to install the latest security patches and upgrades to make a difference in the field.

Any initiative that helps administrators to keep their sites - running Drupal or anything else - safe is good.

Oct 07 2008
Oct 07

In Drupal, you can provide a description for each term in a taxonomy vocabulary. The default taxonomy term pages of Drupal 6 include the description at the top of each page (if only one term is present). Here's how you can achieve the same thing when using views.

  1. Make sure your theme has a page.tpl.php file. My theme is a subtheme of Zen so I copied the page.tpl.php file from the zen folder into my theme's folder.
  2. Create a duplicate of your theme's page.tpl.php file and call it page-taxonomy.tpl.php.
  3. Edit the new page-taxonomy.tpl.php file and add the following where you want the description to appear (for example at the end of the content-header):
    <?php if ($taxonomy_term_description): ?>
      <div id="taxonomy-term-description">
        <?php print $taxonomy_term_description; ?>
    <?php endif; ?>
  4. Edit your theme's template.php file and add the following function:
    function yourtheme_preprocess_page(&$vars, $hook) {
      $term = taxonomy_get_term(arg(2));
      $vars['taxonomy_term_description'] = filter_xss_admin($term->description);

After you clear your theme registry - by visting the admin/build/modules page - the term description will be displayed at the top of the page showing your taxonomy_term view.

Sep 27 2008
Sep 27

Lately there has been some discussion about the number of posts (and their quality) on Planet Drupal.

Personally I don't think Planet Drupal is hard to follow because of the large number of posts. There are plenty of other high profile planets with far more posts per day.

Let's compare:

Planet Posts per day Feeds aggregated Mozilla 18.2 234 Ubuntu 17.5 271 Apache 15.9 160 GNOME 14.1 254 Drupal 12.5 261 Android 7.6 21 PHP 6.6 97 Eclipse 6.3 169

Note: The number of posts per day is based on the Subscription trends for the last 30 days of my Google Reader.

The question whether all posts on Planet Drupal are on-topic is harder to answer but in my opinion Planet Drupal is doing just fine. I would say that at least 95% of all posts are Drupal-related. People familiar with Planet Apache will confirm that you have to look really hard to find any posts about Apache software among all those holiday pictures.

It is probably true that not all posts on Planet Drupal have the same high quality writing - I'm not even convinced that this posts has - but that is all part of the mission of Planet Drupal: "Planet Drupal aggregates broadly appealing, Drupal-related blog posts pertaining to the community at large (code, advocacy, marketing, infrastructure etc.)".

In the end, it is really easy to skip a post in your favorite feed reader, isn't it?

PS: I think it is far more annoying that the feed of Planet Drupal contains only teasers instead of full posts. Whenever something really interesting appears I have to click to read the full post. Most other planets only accept feeds with full posts.

Sep 11 2008
Sep 11

Lately, I’ve had various frustrations with Drupal which have moved me away from using it for various things. I’d like to go through where I’ve moved away from Drupal, why I’ve made those changes, and my future Drupal decisions.

WordPress rather than Drupal blog

To begin with, this blog is now on WordPress rather than Drupal – and I have to say that I’m loving it… and so are my non-geeky colleagues. It ticks all the right boxes. Its *really* user friendly. Its much easier to add photos (and videos) to posts. And it’s hardly taken long at all to setup.

So where did Drupal go wrong with this? Well, I guess its the ‘kitchen sink’ approach back-firing. In trying to be something to everyone, Drupal runs the risk of being less than perfect to to any one specific task too. WordPress, on the other hand, has the ability to focus on being the very best blogging software out there, and nothing else gets in the way of that or deters it from its ultimate goal.

But also, we needed to seaparate the business end of our website (the creation of yearbooks, using tens of thousands of nodes) from the nodes and users to do with the blog, partly because around this time every year we flush out the old site and start a new. So we were either going to have a separate Drupal install for the blog or use WordPress. We chose WordPress.

Form theming frustrations

Have a look at the form here and let me know how you’d create it using FAPI (we’re on Drupal 6.4). I’m talking specifically about the theming of the form. Yes, its a very simple form. A search form. But let’s have a look at what’s going on with it and discuss the Drupal way versus the way we ended up doing it.

In FAPI, you’d probably have a ‘textfield’ element for the search box and a ‘submit’ element for the ‘Go’ button. Easy enough, one minute of code. But what about the title ‘Name of your school or group’? Probably a title for the textfield element, no? But then how do we get it centred above both the textfield and the submit button? And what about the text under the two fields? A description, right? Again… how do we get it to appear *exactly* where we want it? The look and feel of the form are to me absolutely crucial. I don’t just want a textfield’s title (with annoying colon after it), a textfield, a description, and then a Go button all one on top of the other.

The Drupal solution? Using a theme hook. We define the form in our implementation of hook_form() and then theme that form separately. The ‘programmer’ cares about the functionality of the form but not the visual design of the form. The ‘designer’ doesn’t care about the functionality and instead works on how it looks. But I’m both the programmer and the designer here, and I want my work to be as easy as possible! So, let’s say i go down this route (I tried, I really did). I need to register my theme function in hook_themes(). Okay, I know why, it saves extra code running on every page load. But its still annoying. Now I create my theme function… urgh. You’ve got to really know your FAPI stuff to get this to work. I try for a while but then I give up. It just feels so messy with some code somewhere, some in another place, and then when I ask my colleague to have a look so he can learn how to do it he’s disgusted… doesn’t know what’s going on… starts bad-mouthing Drupal. So we build our own massively simple FAPI instead in about half an hour that does just what we want it to do.

So now we’re using our own super-basic FAPI for this form. Not all forms, just the ones we want complete control over, visually. Rather than using hook_form() and defining a form array, we just hard-code the HTML for the form. Some of you may be in complete horror now thinking about this but its just by far and away the easiest way to get forms to do exactly what you want. Like a forename and surname field side by side rather than one on top of the other, sharing the title ‘Name’ which is a label for the forename field.

We’re sticking with the idea of a validate() and submit() hook though. I like that one. But we’re doing it slighly differently and more simply, so that any new coders we might hire can quickly and easily pick it up.

Going nodeless

I don’t always like nodes. I really, really don’t. I don’t need revisions, and if I did I’d do them in my own way, just the right way for me, rather than a way that kind of works for everyone but not quite perfectly for anyone in specific. I don’t like the way that as uid=1 I get all the extra bits like ‘Authoring information’ which I never touch. Node hooks and the nodeapi which I once loved are now a higgeldy-piggledy mess that’s a real pain for my new hire. I try to explain to him what’s going on when I save a node. “So this function deals with the submission. But not the core node stuff, Drupal deals with that. And if we want something used for all nodes, we put it in here instead. And we can also override this specific bit here.”… he looks on in amazement, totally baffled by what’s going on and why. It would be so much easier for him (and me) to understand if everything’s just in one place.

So what do we gain from nodes? Umm… not much really. We don’t use contributed modules any more because they never do exactly what I want and always do stuff which I don’t want them doing which just make them less efficient. We put all our code in our own one module instead. A massive, hefty module with a dozen or so include files.

We gain the ability to always do $node->nid and use node_save() and other handy things. But we don’t really need nodes, and it frustrates me having to do the extra INNER JOINs on node_revisions etc. So we’re trialing not using nodes at all for one of our content types – our customers. We just have a simple ‘id’ field now in one single table. We no longer need to INNER JOIN node and node_revisions. We haven’t had any problems so far, but the new hire is finding it much easier to code now, without the ‘baggage’ of Drupal.

The future

Our current plan is to gently migrate away from Drupal, perhaps altogether. We like the idea of building our own framework again, one that does exactly what it needs to do for our site. Its not something we can do overnight. Ours is a yearly cycle, following the academic year, and the current plan is to fork the codebase in around January/February and that would mark the beginning of our own framework if we still feel that way then.

In the meantime, we’ll continue using nodes for most of our content types (if simply because migrating away from them would be a long and arduos task with little reward) and we’ll continue to use FAPI for most our forms. But I see us using our own simple FAPI for more and more forms where we need complete control over them, and I see us extending this FAPI to help us reduce using the same code multiiple times.

I think I still like Drupal. I definitely appreciate the vibrant community. But sometimes I thoroughly hate Drupal and get massively frustrated by it. But I still like it in theory at least. One framework for all my websites. But whilst I just work on one massive website it just has so much less use to me.

You’re more than welcome to urge me to stay with Drupal. In fact, I highly hope someone can manage this. I’ve put a lot of time over the last few years into learning Drupal, and it would be a great waste and a shame to lose all that.

Share this:

Like this:

Like Loading...
Sep 01 2008
Sep 01

I eagerly awaited the videos for the Boston Drupalcon. They never seemed to appear. 

However, the videos for Szeged are already available here ! The quality is very good. Audio is good and the presentation screens are fuzzy but you can get the general idea. 

Very impressive. There are many hours of must watch video here if you were unable to attend the conference live.

Aug 26 2008
Aug 26

Recently I have upgraded a customer site from Drupal 5 to Drupal 6. The site contains a number of custom modules that required considerable work because of some changes in the Drupal API. One of the API changes is the removal of hook_info and hook_auth.

The new authentication mechanism has two advantages:

First of all, two authentication-specific hooks have been eliminated. There is no replacement hook, instead you must use hook_form_alter to replace the built-in validation functions of the user login form. This is a more general and more flexible approach and it shows the power of the current form API. You can check user_login_block and user_login_default_validators for examples.

Secondly, there is a lot more flexibility to do error reporting when authentication fails. In Drupal 5 when hook_auth returned false, Drupal would always display the error message "Sorry, unrecognized username or password. Have you forgotten your password?" even though the real problem might be something else, for example a remote server responsible for doing the actual verification of the password is not available. In Drupal 6 you can fully control which messages get displayed during an authentication failure.

Even though there is some work involved to migrate custom authentication functionality to Drupal 6, the end result is code that is much cleaner and more powerful.

Aug 22 2008
Aug 22

There is an interesting presentation by psychologist Barry Schwartz at TED called "The paradox of choice". He explains why people are not better off when there is too much choice.

He claims:

Some choice is better than none. But it doesn't follow from that, that more choice is better than some.

His explanation makes sense:

The more options there are, the easier it is to regret anything at all that is disappointing about the option that you chose.

I think he has a valid point. A point which is also true in software:

I'm not saying that there should be no choice at all but very often there is simply too much choice and investigating all possible options takes too much time. Luckily Barry Schwartz reveals how to be happy with the choices you make:

The secret to happiness is "low expectations".

You can watch the presentation below or over at TED:

Aug 09 2008
Aug 09

After over three years as an independent web developer, I've had an opportunity drop in my lap that I am going to take advantage of.

WorkHabit is in the process of opening up shop in San Diego, and I'm joining them. They've got a top-drawer team, and they don't do background checks, so it's a perfect match for me.

I've enjoyed working independently for the last several years, however, I've also learned a lot about running my own business. The primary lesson I've learned is that running a solo web development shop involves a lot more than web development chops. I've spent more time than I would have liked doing things like billing, support, follow-ups, "sales", and all the various tax and legal oriented tasks that come with working for oneself. 

I consider myself a worker bee. I love web development. All the other stuff, not so much.

WorkHabit is truly committed to contributing to the Drupal community. This is a must-have for me. I truly believe that no Drupal based shop can thrive without being directly and heavily involved in it's people and development. I've got a thing against obviously successful Drupal businesses that take but never give. It's just wrong and not too smart. WorkHabit gets it, and I'm looking forward to being able to increase my work with and contributions to the Drupal community. 

I'll be working alongside Drupal Dojo host Joel Ferris (senpai) and Michael "mad man" Murdoch (froggacuda), helping create WorkHabit's San Diego presence. 

We are going to be more heavily supporting the local San Diego DUG in the future as well.

Jul 30 2008
Jul 30

Unless th' list is crazy long, like it can be fer operatin' systems, I realized that I read software changelogs pretty closely. This site now has one, with an RSS feed. It will be a sort o' commit message, listin' additions an' changes worth mentionin' about th' live site. (Can somebody remind me later on t' tell ye how I setup me stagin' environment? Aye, fer a personal blog.) It will not include updates t' tha Drrupal modules run on th' site unless it makes a dramatic difference. The changelog will include changes t' layout or th' underlyin' tha Drrupal theme an' addition o' content sections. The first entry? That I created a changelog in the first place. You can find out which version o' tha Drrupal I'm runnin' via th' usual open secret method, though I will make a note o' it when I do upgrade.

May 21 2008
May 21

Not long before my old laptop got to the end of it usable lifespan I started playing with the Zend Framework in my spare time. One of the cool things about ZF is that it wants to use friendly URLs, and a dispatcher to handle all the requests. The downside of this approach, and how ZF is organised, it works best if you use a Virtual Host per project. At first this seemed like a real pain to have to create a virtual host per project. One Saturday afternoon I worked through the Apache docs in search of a solution - then I found it! Rather than bore you with more of my views on Zend Framework, I will explain how to have a virtual host model that requires a little work up front and is very low maintenance.

It gets tedious copying and pasting virtual host config files each time you want to start a new project, so instead I let Apache do the work for me.

I added a new virtual host config file called projects to /etc/apache2/sites-available. The file contains

UseCanonicalName Off

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon

Options FollowSymLinks
AllowOverride All

    ServerName projects

    CustomLog /var/log/apache2/access_log.projects vcommon

    VirtualDocumentRoot /home/[username]/Projects/%1/application/www
    AccessFileName     .htaccess

The important bit is the VirtualDocumentRoot directive which tells Apache to map a hostname to a path. I use an IP address from the range for the virtual host, so they aren’t accessible to the outside world and I don’t have to worry about it changing every time I check locations.

All of my projects live under ~/Projects and each one gets a directory structure that looks something like this.

  +- notes - coding notes, like grep output when refactoring etc
  +- resources - any reference material or code snippets
  +- application - the code for the project
     +- www - document root for vhost

There are usually other paths here too, but they vary from project to project.

To make this work there are few more steps. First enable the new virtual host by running sudo a2ensite projects. Don’t reload Apache yet.

Next you need to add the Apache module with sudo a2enmod vhost_alias. Now it’s time to edit your /etc/hosts file so you can find the virtual hosts. Add a line similar to this: projects phpgw-trunk.project [...] phpgw-stable.project

Now you can restart apache by calling sudo /etc/init.d/apache2 reload.

This is also handy for developing client sites - especially using drupal.

Now my /var/www/index.html is just an empty file.

I am getting a bit bored with adding entries to /etc/hosts all the time. If I get around to adding dnsmasq with wildcard hosts to the mix, I will post a follow up.

This setup is based on my current dev environment (Ubuntu Hardy), but it also works on older versions of Ubuntu. The steps should be similar for Debian and derivatives. For other distros, it should work, just how to make it work may be a little different. Feel free to post tips for others in the comments.

Mar 16 2008
Mar 16

The number of available Drupal modules is continuing to grow dramatically. Like a lot of other Drupal users, I spend a good deal of time downloading new modules and trying them out to see what they do. Unfortunately, not all contrib modules work as advertised. I may spend several hours working with a new module before realizing there's some small issue with it that prevents it from solving my problem.

Similarly, there are often modules out there that solve problems I didn't even know I had, but I'm simply not aware they exist.

What I want is a resource that leverages the experience of thousands of Drupal administrators. I want to know that I shouldn't even bother with a module because it's too buggy. I want to know what modules other users find useful in specific areas (such as multimedia, file handling, cache issues, etc.).

Other large OSS communities often solve this need for a shared knowledge base by providing user reviews. Mozilla, Thunderbird, Joomla and other modular systems provide user reviews and ratings. It is time that the Drupal community have one too.

When I first started using drupal about three years ago, it was not all that difficult to simply be aware of most modules and how effective they were because there just weren't that many. Now there are multiple new modules released on a daily basis, and I just can't keep up anymore.

Why do we, the Drupal community, not have a shared review/rating system? It's certainly not due to lack of demand. A search for "module ratings" on Drupal.org reveals a great deal of interest in this functionality.

As far as I can tell, the primary reason for not having a rating system for modules is fear. Module developers in particular are concerned with the fairness of ratings. They are concerned with "gaming" of ratings. They are concerned that inexperienced or "dumb" end users may unfairly give a bad review of a module simply because they don't understand how to use it. These are all reasonable concerns. But they are concerns shared by other OSS projects as well. Sure you will see "bad" reviews, giving a module the lowest possible rating along with some inane review such as "tis modules sukcs BEWARES" :) But who cares, it's just noise that will be drowned out by valid reviews. It works for other OSS projects, and it can work for Drupal.

John Forsythe
has released what I believe is the first site dedicated to rating and reviewing Drupal modules drupalmodules.com. No doubt this site will be a source of controversy as developers voice their concerns. But we need this resource now.

I encourage my entire audience (hi, mom!) to register at drupalmodules.com and to submit reviews for both your favorite and most hated Drupal contributions. This is a great way for non-techies to contribute to the community. The site is young, and there is naturally a shortage of ratings on the site now, but that will change as the site brings on more users.

Maybe this database will eventually make its way to Drupal.org. For now we can show our support for this type of system by helping build out the database at drupalmodules.com.

Mar 12 2008
Mar 12

Here’s a pretty basic css technique I’ve noticed myself using a lot of lately (not at all my own invention). The divs used as examples come from zen theme.

Often a design calls for putting a background (or border) on a sidebar. It should look as so:
If you haven’t been down this route before, you will probably try something like

  background: #123456;

As long as your sidebar is longer than your content you will think you have succeeded, but go to a page with long content and you will see:
short sidebar
Argh! We want the sidebar background to go all the way down the page!

You’ve learned not to overthink when you’re dealing with css, so next you might decide to give the whole page the sidebar color and then give the content section its own background on top of that. This simply gives the opposite effect:
long sidebar
Now things only look right when the content is longer than the sidebar.

The easiest way to get things straight is to just suck it up and take it to Photoshop. Make an image with a 1px height and a width the same as your sidebar. Instead of applying the image as the background to your sidebar, you’ll apply it as the background to the whole page.
bg image

#main {
  background: url(images/sidebar.png) repeat-y top right;

If you have two sidebars, make one image the full width of the page.

You had to use Photoshop.
You can’t easily change your sidebar width.
You have to load one more image per page.

You’re done!

The same principle is very useful for theming panels. Panels are made up of one or more rows which each have one or more columns. Once you put content in the columns of varying height you get one ugly panel:
panels hell
Do your panels kind of look like this too? Not good. This panel has two rows, and each row has 3 columns. Note that the second element in the second row’s first column (bottom left!) is actually a mini-panel containing two columns. Although the panel has a grid-like structure, the fact that all the content has varying heights makes it look like a mess and probably nothing like your designer’s mockup for your front page.

Adding backgrounds to the content will bring back order to the panel. But once again if you apply the background directly to columns you will end up with:
panel backgrounds
What you really want is more like:
panel heaven
This is the kind of thing that I imagine was really easy back in the days of table-based layouts. Now that the web is all about dynamic content in divs of unpredictable heights, these kinds of things are more difficult. The answer is to, as in the sidebar example, create a background image for each row and tile it vertically.

Now your panels can have the tabled look they seem to be begging for and without the embarrassment of actually using tables! Does anyone have a preferable technique?

Mar 03 2008
Mar 03

Error message

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls in menu_set_active_trail() (line 2405 of /home1/markspap/public_html/kathy/includes/menu.inc). March 2, 2008

It's been a good, long while since I wrote a blog post. Between work and family, there just hasn't been time. I've been super busy for months now, but not without some benefits.

For one thing, I've been learning tons. I've been working on picking up more PHP and delving a bit more into backend Drupal work, as well as doing more accessibility and usability work and learning more about user experience design. I guess you could say I've been branching out every which way. As a reward for all that hard work, I'm going to DrupalCon in Boston. Although the conference doesn't start until tomorrow, Jon and I flew in for a long weekend to soak up some history and not a little seafood. I can now state pretty definitely that the Union Oyster House has the best clam chowder I've ever eaten, and Mike's Pastry has Boston Cream Pie to die for. Not to be missed. It might be cold here in Boston, but with good food and four whole days of Drupal learning, it's weather I'm happy to put up with.

Similar Notes

Feb 16 2008
Feb 16

The importance of project management tools is almost never fully appreciated. I am shocked at how common it is for a group of developers to go working without version control, ticket tracking, development documentation and so on. The very first thing I do when working with a new client is to make sure that they get these tools in place if they haven't already.

Those who are used to working without a complete set of project management tools never fail to appreciate the benefits of them once they are introduced. I consider it next to impossible for a team to work together without managing code and tasks in an efficient and highly organized way.[img_assist|nid=155|title=|desc=|link=none|align=right|width=250|height=156]

Hopefully you do not need to be sold on this idea and are using CVS or SVN to manage your project already. You likely have some sort of ticket system. It is a little less likely that you have both of these components integrated with each other.

When it comes to choosing a solution for project management software, a die-hard Drupal user has a dilemna. On one hand, Drupal seems as though it should be the perfect solution. It's fully customizable, has lots of nifty project management related modules and, most importantly, it's Drupal! Why would you not use it? "Eating your own dogfood" is the way to go, right? Meh...

Drupal is generally considered a content management system. Personally, I like to refer to it as a website management system. It is great at managing website related stuff like users, posts, permissions, categorization, and so on. Using contrib modules, you can customize and enhance this core functionality to almost no end. But at the end of the day, Drupal is designed to handle web content and the users that are accessing it. That's what a content management system is (and if content is king, that would make Drupal... well... God).

Managing a project, on the other hand, is a much different business from managing a website. Yes, you have many shared properties such as content and users. But the essence of project management involves things that have nothing to do with website management such as a revision controlled code base edited by multiple users, a need for efficient ticket management, and ideally full integration of everything. Essentials also include stuff like a nice repository browser, user management interface for repository access, fancy reporting for tickets, organization of tasks by milestone, date, person, severity, etc...

It's a very tall order. Yes, you can do all this in Drupal, but not very well. You can piece together something that sorta kinda resembles a project management solution, but in the end, you need to invest a relatively large amount of time to create something that is less than ideal and will require ongoing tweaking and modification. Unless your business is creating an effective project management solution in Drupal (something I dream of!), you should not be using Drupal for project management.

I'm a one man shop, and I do not have time to spare. I cannot justify spending any time at all kludging together a project management solution for a client when there are already far superior solutions available at low cost. I would much rather pay someone a few bucks a month and be done with it. Let them deal with SVN administration and enhancements; let me focus on my primary task which is building cool sites with Drupal.

While there are numerous project management related service providers out there (Fogbugz, Basecamp , Beanstalk to name a few), I want to talk about my personal favorite, Unfuddle. Unfuddle has taken obvious inspiration from the folks over at 37signals, innovators of the simple, clean, effective, it-just-works web application. Unfuddle is an instant project management solution that takes minutes to set up and costs a few dollars a month. The time you'll save in not having to set up SVN and manage SVN users alone makes it worth every penny.

[img_assist|nid=156|title=|desc=|link=none|align=left|width=250|height=221]What you get with a solution such as unfuddle is a ready-to-use repository with integrated documentation, ticketing and reporting. It takes seconds to set up a new user account with permission levels fit for everyone from a developer (gimme root!) or a suit (look but don't touch).

From a single interface, you can browse code, tickets and documentation. Every component integrates with the others. You can even resolve a ticket with an SVN commit message, saving you the trouble of having to go and edit the ticket after your commit! Users can individually subscribe to whatever level of email notificaton they would like to recieve and how often. The developer can shut off all notifications while the manager can get a nice daily summary each morning of milestone completion progress, new tickets, added documentation and so on. The project manager can glance over one of the ticket reports and group tickets into milestones for reasonable short vs long term goals.

SVN comments link back to the tickets they are related to. Tickets contain links to the changesets that resolved them. Viewing these changesets, you can see a beautiful code diff and quickly see what fixed the problem. Senior team members can quickly and easily review code changes submitted by junior staff.

With tools like this available these days, it's just not worth it spending any effort whatever on a lesser solution.

Feb 12 2008
Feb 12

The CCK ‘display fields’ settings are very useful for theming nodes by content type, but I often find myself having to get further into customizing node output field by field.

Once I decide there’s no way getting around taking finer control of my node’s fields, I create a node-{type}.tpl.php by copying my existing node.tpl.php and open up Devel’s ‘Node Render’ tab. Then I delete the $content variable from the template and start adding things like

print $node->content['field_image']['#value'];


print $node->content['body']['#value'];

The $content variable is nice for amateurs, but we need the unrendered $node->content to get good control of a node.

While this gives me complete control over the output of the node’s fields, the drawback is that now if I add a new field to the node, or if I add a module that adds something to $node->content, I have to go back to my template and add in this new element. Because I often do my theming and development in parallel, this can be rather annoying, and there is also a danger that I could overlook doing it.

Therefore I think it may be more practical to use code like this in the node template:

foreach($node->content as $key => $field) {

Instead of printing each field that is wanted in the template, I can instead unset the fields that are not wanted and then print all the fields. This is faster to write and it lets any new fields show up. After unsetting unwanted fields it looks like this:

foreach(</span>$node->content as $key => $field) {

(I found that I need to unset $node->content[‘#children’] to get this method to work correctly.)

Now if you want to control the output of specific fields individually you could add a switch:


foreach(</span>$node->content as $key => $field) {
  switch (
$key) {

'</span>. $field['#value'] .'


'</span>. $field['#value'] .'



Now I know that these template files are not supposed to get all mucked up with php, so this method is really just a hack and won’t be appreciated if you are working with a designer who dislikes php. But if you, like me, were finding yourself dissecting $node->content into crazy pieces with tons of php in your node templates already, perhaps this method could be a slight improvement.
Feb 07 2008
Feb 07

I should consider becoming a salesman for Drupal because I am always talking about how good it is. But it really is. If you are not using Drupal you have 2 options:

  1. Get Drupal
  2. Suicide

Although suicide may sound appealing you're probably better off just downloading Drupal. Once you download Drupal here are some key things that make it so powerful:

  1. User Accounts

    Being a programmer myself I can tell you that coding this type of thing is not fun. It requires a lot of form checks and admin pages. It's just not something you wanna do. But Drupal developers do (thanks Dries)!

  2. SEO

    I went from 23 visitors a day to 14,000 a day after switching to Drupal. No, not really but I can tell you that Drupal is very good for SEO. It has the internal link structure dialed in pretty well and each "keyword" goes on it's own page with a title of your choice. Google likes and I like.

  3. Theming

    The theming is broken down very nice in Drupal as it allows you to treat inside "nodes" or articles inside your site different from your "page". It also allows you to theme your comments and sidebars and all that stuff. You can also over-ride functions from modules, but that's a more advanced topic.

  4. Scalable

    Gone are the days of installing the same files over and over again on the same server. With Drupal all you need to do is slap one install up on your server and you're good to go. Any additional sites can access the same files and use the same modules. You can share databases or split a new one off for each site.

  5. Modules

    Drupal has a ton of modules that are available to download at your convenience. These modules cover pretty much anything you could ever think of except it doesn't quite offer the "Facebook Clone" module yet.

  6. Management

    Management is a breeze with Drupal. You can easily view all your posts, users and reports. You can unpublish content and comments if you don't want them to be seen. You can ban users or IPs. You can change the positioning of elements on the site in real-time and lots of other fun things.

  7. Time

    Unless you have at least 5 years of spare time on your hands to dial in your own CMS I recommend you download Drupal.

  8. FREE

    It's freaking free. I've seen companies switch from paid CMS's to Drupal cause they realized sometimes bad decisions can be remedied. I've seen people unload a full set of rounds and hit nothing but air... whoops! Drupal isn't The Matrix (yet).

Research Conclusions


(No seriously, I'm not paid to write this.)

 Filed under: Internet / Tech, CMS, Drupal
Feb 06 2008
Feb 06

I often find myself needing to get rid of some of the sections on Drupal’s ‘My Account’ page. Not every site needs it to say ‘History: Member for 1 day’ for example, and if you use a lot of contributed modules that screen can get cluttered fast. So this morning I got sick of dealing with it, found there is a perfectly good hook_profile_alter there to work with, and wrote a little module to let administrators disable these fields. Let me know how you like it: http://drupal.org/project/myaccount_alter (currently Drupal 5 only)

Feb 06 2008
Feb 06

If you work freelance like I do, you know that time is money. I’m always trying to shave a few more seconds off my development time. Here are a few tips and tricks that I constantly use:

  • Firefox Wildcard Bookmarks

    Set up some bookmarks with keywords shortcuts and wildcards. I have a bookmark for the forms api reference so that I only have to type ‘forms’ to get to it. I also used this method so that I can quickly look up api functions. I used a similar wildcard bookmark for project pages. Now if I’d like to see the views page I simply type in ‘pr views’. Not only does this save me a lot of time but it also encourages me to go check out modules I might have otherwise put off looking at since it seemed like a slight hassle previously.

  • Drupal CVS shortcut

    I check out a lot of modules from Drupal’s CVS. With Drupal you can just about build a website as fast as you can check out modules. Well, almost. I constantly had to look up the terminal command for cvs checkout until finally I got wise and set up an alias. On my Mac I did this by

    cd (go to your user home directory)
    vi .bash_profile (edit your bash profile in a unix editor I am just not quite geeky enough to have mastered. Alternatively, if you’ve set up Textmate properly you can do ‘mate .bash_profile’)
    Now add the line: alias drcvs=”cvs -d :pserver:[email protected]:/cvs/drupal checkout”

    Now when I want a module I type: drcvs -d {modulename} -r {version} contributions/modules/{modulename} . This I can actually remember.

  • Drupal navigation

    You need to get into admin_menu and/or teleport modules. I’m going to stop giving out links to every great module since by now you should have created your firefox wildcard project bookmark.

  • Parallels (Mac)

    Launching Parallels is faster than Bootcamp or getting up and turning on your old PC. Personally I believe if you’ve so much as touched your client’s css that it is now your moral imperative to recheck everything in both IE6 and 7. Bonus tip: run them both.

  • Firebug

    Firebug is the best thing that ever happened to css as I’m sure you’re aware. Make sure you check which line number of which css file you need to change and then use your text editor’s keyboard shortcut to go straight to that line. I like to use Firebug for anything I might have previously used ‘view source’ for as well. You can make sure that new css or js file you added with drupal_add_css or drupal_add_js loaded properly on your page. Find out your keyboard shortcut to go straight to inspect mode (mine is shift-command-c). I constantly use inspect mode to take a look at the relevant markup. Often if you need to find a theming function a Firebug glance at the markup will give you something to search for in your text editor. It may also give you a hint as to the form_id you’re trying to hook_form_alter.

  • Firefox search

    Go to your Firefox preferences and under General:Accessibility check off ‘search for text when I start typing’. Now you don’t need to hit command-f to search on the page. When you go to admin/build/modules to enable your new module, just start typing the first few letters and you’ll jump down to it on the page. Congratulations: you’ve just saved 200ms. Well, everything adds up.

  • Use your editor

    Mine is Textmate (Mac only) and it’s pretty great. Although you might be tempted to just type a little php in a block edit textarea or similar place, I find that this usually costs me more time than it saves because half the time I mess up a bracket somewhere. If your block is fairly complex you’ll really be glad down the road (probably three minutes from now when you want to edit it) that you took the extra minute to call hook_block in your custom module. If I really do just need to insert a little php, I still write it in my editor and then paste it in. This spares me the otherwise inevitable debugging. I think that doing things right is almost always faster than doing them fast and possibly having to debug them later.

  • Submit a patch

    This might not seem like a time-saving tip but I’ve come to believe it really is. It turns out the only difference between being a frightful Drupal hacker and an esteemed Drupal contributor is whether or not you submitted a patch. I used to always hear “don’t hack Drupal” and wonder how the hell these people thought that was possible when surely we all know there are dark corners of code where the override and hook systems never reach. Finally I realized they probably just submit a patch and call it ‘contributing’ instead of ‘hacking’. Actually I didn’t realize this until some point after I joined them.

    When you get in the habit of submitting a patch immediately after debugging or adding a new feature to a module, it will only take you a few minutes to do. The time savings comes from the fact that you now have other eyes on your work. Sometimes the module maintainer will turn around and point out to me a bug in my patch that I hadn’t yet tested for. Usually they will eventually commit my patch, which may be a time-savings for me on some future project or when upgrading the current one. Or they might give me a tip like “upgrade to my latest version you idiot because it’s actually way better” which is valuable to know. Maybe they will like my code so much that they will offer me marriage or employment, which could be side benefits on my time-saving mission.

Feb 03 2008
Feb 03

CFDV.org is the website for the The Chromatography Forum of Delaware Valley. Chromatography is a discipline of chemistry which is used to separate mixtures for analysis. For example, when your aspirin is tested to be 99.7% pure that was determined with chromatography by an analytical chemist. Likewise when your urine is tested to contain marijuana that was also determined by chromatography. Chromatography is a complex science and is used extensively in the pharmaceutical industry- an industry which has a large presence in the Delaware Valley. The Chromatography Forum is an independent organization which educates and unites scientists who are interested in this field.

I got the opportunity to build the CFDV website through my work friendships in chemistry (I was a chromatographer before learning web development). It was my first freelance project and was built in Fall ‘06 prior to my involvement with Drupal. Fortunately I convinced the forum to have me rebuild the site more recently in Drupal 5. In rebuilding the site (which previously had a homemade CMS) in Drupal, there was almost no change visible to the casual visitor but the site’s administration became streamlined and best of all the site’s potential for new functionality is extremely enhanced.

The site makes extensive use of the Date API and does some interesting things with dates and menus. When you click on ‘meetings’ it takes you to the next upcoming meeting and names it by the month it occurs. ‘Previous meetings’ uses the nice integration between date and views modules to give a very specific range and sorting of meeting nodes (the forum uses a September - June year which complicated the problem).

The site also takes reservations and payments by paypal for both meetings and courses. The meeting reservation form is just a fancy cck type. It passes the node id of a meeting as an argument to the node/add/registration page, and uses that to add relevant information and populate the meal choice. Then I used a lot of hook_form_alter and some jquery to further refine the form (it dynamically shows more fieldsets for additional guests in your party). I created a custom action to send the reservation to the CFDV administrator as well as the guest. I used lm_paypal module to integrate the site with paypal and allow the guests the option to pay online after reservation.

The course registration system is more complex than the meeting reservations, so for this I opted to create a custom multistep form using the Drupal Form API instead of relying on cck. If you’ve made it this far in this article you might already know what a hassle it is to make multistep forms in Drupal 5. You finish everything and then the client would like the form to have a back button (which I don’t think is really possible in the current API). The beauty of the course registration form is that its options are automatically created by the existing content of the course nodes on the site. All the courses and their options and prices and early-bird discounts already existed on the site as course nodes and with this wily form and my inherent fear of redundant data I made form magic come alive. (Other than being able to change the text at the top of the form, there is no maintenance required for this form at all.) I did some jquery work on the checkboxes on the form, so that only sensible combinations of box-checking can occur (checkbox wizardry). I also made the completed form save its data into an unpublished node for future reference. Then I hacked lm_paypal so that this new node’s id would be passed to paypal as an item number. Then when payment is completed and the item number is returned by paypal’s IPN, an action is fired to email the site administrator the contents of the saved node. Actually the most interesting thing about this form is that it is actually working! Next time though I might look into Simple Paypal Framework as well as lm_paypal module, to compare features.

It’s nice to work at enhancing this site and see its role with the organization evolve. There is quite a bit more use I can see the organization getting out of this site with future functionalities. Drupal sites can be much more than what you might traditionally think of as a website and also serve as software to automate things you may have been doing manually in your organization. I like the idea that a website is not one more thing an organization has to deal with updating but actually a tool that simplifies their workflow. I think that the custom forms I made for this site do exactly that, and that there is a lot of potential for this site in the future to serve as an online community for this group of scientists.

Jan 24 2008
Jan 24

One project I’m currently working on which is already live is OnlyAlummni.com.

Instead of having to build the entire site, I have a smart client who set up the site and had me work only on the trickier (fun) parts of this project. OnlyAlumni is a social networking site with about 8000 colleges, fraternities and sororities which operate as Drupal organic groups. This has been a great project for me to go much more in depth with organic groups and related modules.

The best part of the project has been getting to use Panels 2. The group homepages, user account pages, and user home page (for logged-in users) all rely on Panels 2 and made everything mind-bogglingly simple (if that’s possible) once I got my bearings with Panels 2 and its changes from alpha to beta mid-use.

The most complex part of the project so far has been the tracking of site activity. The site does something similar to Facebook’s news which lists site activity among your friends. For onlyalumni.com we are listing all site activity, the activity of your friends, and the activity in your groups. After coding all this in an insane way I wasn’t satisfied with, I found out about the activity module which seeks to do this the right way (saving activity to the database rather than trying to look it all up on the fly, and using the amazing token module to customize the output.) Because activity module is under active development and wasn’t doing everything I needed, I wrote a bunch of code for the project and redid OnlyAlumni’s activity tracking to use the module. This lucky chain of events all started in Portland where I met handsome lads Jerad Bitner and Robert Douglass who are developing activity module.

I also enjoyed using imagecache profiles module (which became an actual module around the time I was using it from its original incarnation on Nate Haug’s Lullabot article). The point of the whole thing is that it makes your user avatars all the same shape (usually square) without asking your users to do anything special, which lets you make nice little grids out of them.

If you want to get the full effect, go ahead and sign up for an account and join your college alumni group: http://onlyalumni.com


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