Tuesday, 9 December 2008

Drupal 6: Core hacking for the simplest of things

I was recently faced with a problem concerning changing something in Drupal's core user module. This wasn't even a big change; it was as simple as changing the line of text that appears underneath the username field on the registration form. You know, the one that helps the user to choose an appropriate username.

The core has no option for changing this text, so the most obvious and worst thing possible is to open up user.module in the core and edit the string. This is bad because the first rule of Drupal club is do not hack the core. Actually, the second rule of Drupal club is... you get the idea. It would mean that when Drupal is upgraded, the change will disappear.

After ruling out the above method, I was faced with a number of opportunities to accomplish what I needed, but they all came with downsides.

Override the core


This involves making a copy of the core user module inside my site's modules folder. Drupal will then use the copy instead of the one in the core and changes can be made safely to this copy, because it is not going to be upgraded when a new version of Drupal is released, unlike the core itself.

My main concern here is that technically it's a core hack in disguise. In my case, I would be making a copy of Drupal 6.6's user module and then changing it. But, what happens when Drupal gets upgraded to 6.7? The core user module will be 6.7, but the site won't be using it. Any new or changed functionality in the user module will be missing from the site, and worse, this could introduce incompatibilities.

Suppose something has changed in 6.7's user module, and the other core modules expect this change to be in place? This would break Drupal, because it's not expecting to encounter the 6.6 user module here. How likely is this to happen? I'd say very unlikely in an upgrade from 6.6 to 6.7, but still possible. More than that, it's far more likely to happen once 6.7 becomes 6.8, 6.9 and so forth.


Locale


Drupal's translation system makes it possible to provide a translation string for the text underneath the username field, as though it were being translated into French or Italian, but this feels wrong. It's not a ‘real’ translation because we just want to change the string itself, not change it into another language.

String Overrides


There exists a module called string overrides. It provides a way of changing any text that is passed through the t() function, by saving these translations in the variables table. This seemed like an ideal solution at first, but on closer examination, there are a few drawbacks.

Firstly, since the overrides are stored in the database, we lose version control, which is never a good thing. Secondly, the more modules you add to a site, the more overhead there is, both in terms of memory and in terms of processing times.

Custom module


It would be possible to write a custom module specifically for the site in question. The module would mimic the functionality of the string overrides module, but store the overrides in a file instead of the database, thereby providing version control. The only slight downside to this is that it requires a lot more time than the other approaches. It seems like extreme overkill to have to write an entire module simply to change one string.

To conclude


In the end we decided to go with the core override method. I am not entirely happy with this, but I am sure I would not have been entirely happy with any of the solutions I've presented here. I can acknowledge and understand that there are many compromises to be made on the way to a completely custom Drupal site, but there is always room for improving Drupal to accommodate many of the more common requests. The questions are: is this one of the more common requests? and: what is the best way forward here?

4 comments:

Brian said...

There are a couple of things that you could do here. Since in this particular case you are just wanting to change a simple change to the #description attribute of the field, the easiest method is to use hook_form_alter to make the change to that text.

You would want to take a look at drupal's form API (or FAPI as it is sometimes called). This would be a very small and simple module to create and would be much better than editing core (even if the core edit is a simple aesthetic change).

For more intense edits to user.module functionality one might find the need to override actual menu callbacks (these are found in the user.module file in the user_menu function). I find that a great way to do this is to use hook_menu_alter to edit the attributes to point them to my own custom modules. This essentially allows you to completely customize almost any functionality in the core user module.

Brian said...

Quick addition. You did mention that you didn't want to add an extra module, which is a valid point. You could do the same thing through the theme layer by simply using theme_form in your template.php file.

fw190a8 said...

Brian, thanks very much for your input. That's definitely a big help and you've pointed out two options I had not even considered!

Erik said...

In searching for a solution to something similar, I happened upon this post. Since I solved it in a slightly different way, figured I'd share.

http://elementalmarkup.com/ramblings/theming-user-login-block

You can theme user_edit_form() in the same way and just change the

$form['account']['name']['#description']

and return the rendered form.