Theming the User Login Block

By Erik, Sun, 09/27/2009 - 14:42
I had a question posed to me about how to change the "Request new password" text on the User Login block, so I did a little investigation and came across a great article by Addison Berry of Lullabot that did basically what I wanted, but only to a different form. That, plus another article where she details her "Aha!" moments in Drupal theming really pulled the whole thing together and led to a fairly simple result.

The user_login_block function

The user_login_block function is part of the user.module and generates the form for us. This is separate from the individual login, register, and password pages found, just the "User Login" block, but can be easily extended to the others as well. In reading the definition of the user_login_block function, the last part to be added to the form is a section of links: theme('item_list', $items)); ?> The crux of this statement is that there is an array of $items that are themed into an unordered list and given to the form to display. The two items in the $items array turn out to be the two links for "Create new account" and "Request new password". Specifically, the link for requesting a new password: array('title' => t('Request new password via e-mail.')))); ?> The powerful, but short-named l() function creates a Drupal-approved link for us. Without any "translations" from other language modules, this function would produce this HTML: Request new password ?> So, in effect, we want to change this array item to: Forgot how to login?'), 'user/password', array('attributes' => array('title' => t('Click to receive a new password via e-mail.')))); ?> As Addison mentions in her article, you can do this for Drupal 5 and 6 either in the theme layer or by creating a mini-module. I am going to focus only on the Drupal 6 version for doing this in the theme layer. There are two ways that Drupal and phptemplate allow us to prepare HTML output: functions and template files. I think that if you're planning to change much of the form output, .tpl.php files are the way to go. If you're only changing a little bit, for example some text as in our example, using a function seems more appropriate. However, as with many things Drupal, you can do this either way and be successful.

Registering Functions

To let Drupal know that a function exists, it must be "registered". This is done with a special function named theme(). As described in the API documentation:
All requests for theme hooks must go through this function. It examines the request and routes it to the appropriate theme function. The theme registry is checked to determine which implementation to use, which may be a function or a template.
I have a custom theme called "roughy" that I'm using so whenever you see "roughy" or "roughy_", you should change this to match the theme you're using. So to register our override function, user_login_block(), we need to declare it within roughy_theme() and place that code into our template.php file. Here's the syntax for registering our function: array( 'arguments' => array('form' => NULL), ), ); } ?> This let's the theme engine know that we'll be expecting to override or add onto the user_login_block function. Then we can actually build our function. Now, one technique is to copy/paste all of the information from the core user_login_block function and change what we need. This is a good way to do it when you're changing a good deal of the original function. However, since we're only changing a small portion, we can pass in the original form variable and just change what we need. One difference between the original core function and ours is that the original returns the form object, whereas since ours is later in the process, we need to return the rendered form. However, before we return the form, we need to change our text. array('title' => t('Create a new user account.')))); } $items[] = l(t('Forgot how to login?'), 'user/password', array('attributes' => array('title' => t('Click to receive a new password via e-mail.')))); $form['links'] = array('#value' => theme('item_list', $items)); return drupal_render($form); } ?> Once this is in place, we need to clear the "theme registry". This can be done by clearing the caches which can be found under admin/settings/performance or is easily done through the Devel module.

Et Voila

This should be all the changes that are necessary to change the user login block text. You can use this same technique to change the labels for the username or password fields or the value of the submit input element. Next time we'll tackle changing the text on user/pass to give the user more information about what's going to happen. Stay tuned.