webadmin's picture

Drupal theme function overriding

Drupal

For those new to Drupal the term Drupal theming can sound a little scary but really it really isn’t something you should fear!
Drupal theming in its simplest form in just a HTML/CSS layout with a bunch of PHP tags dropped in.

There seems to be a perception that Drupal theming is something really difficult but to be honest if your HTML and CSS skills are up to scratch and you’re open to learning some basic PHP you’ll have no problems.

Drupal can run on different theme engines but as of Drupal 4.7 the phptemplate theme engine became standard, so that’s what we’ll focus on in this tutorial.
What is a theme function?

A theme function is a PHP function withing Drupal that is prefixed with theme_. Theme functions display HTML, and which can be customized by themes.
This is how Drupal.org defines a theme function:
All functions that produce HTML for display should be themeable. This means that they should be named with the theme_ prefix, and invoked using theme() rather than being called directly. This allows themes to override the display of any Drupal object.
How do theme functions work?

Next we’ll need to understand how and when theme functions are executed. In every page load and number of theme functions can be executed by Drupal.

For example you may have a page listing all of the users on your site and this list would call the function theme_username (that we’ll look at more later) for every user in the list to output the users username as a link. This user list may then be passed to another theme function and then finally the content will be passed to the theme_page function which is automatically used by Drupal in order to display your page content within your themes page template.

Modules declare and generally execute theme functions although you can call a theme function from anywhere in your Drupal site (ie. From your theme) providing the module providing the theme function has been loaded.

The great thing is using our themes template.php file we can override any theme function we like without having to edit a single module and this is where using a template.php file becomes so powerful.

Let me briefly explain what I mean by override. By override I mean declaring a new version of a theme function (in template.php) and completely by passing the original theme function in order to alter its output.
An example

Let’s take a look at the theme_username function to explain how to do a theme function override.

Who's New block outputAs I mentioned previously the theme_username function outputs a given users username, so every time you want to display a users username rather than retype a load of code all you need to do is call this function. The "who’s new" block is a great example of where this function is used (see grab to the right). But let’s say you want to change the output of this function so that every time a username is displayed the users user ID is shown after the username, not hugely useful but should give you the idea. It’s fairly simple we just need to override the theme_username function like so:

1. Open up your template.php file that can be found within your themes root folder or if you don’t have one simply make a PHP file and save it to your themes root folder as template.php. By root folder I mean where your page.tpl.php is located.
2. Next open up the theme.inc file located in the includes folder with notepad or whatever text editor you use. This is the file that declares the function we want to override.
3. Find the function theme_username within the theme.inc code then copy and paste the whole function into your template.php file. You can now also close the theme.inc file as we won’t need it again.

<?php
function theme_username($object) {

if ($object->uid && $object->name) {
// Shorten the name when it is too long or it will break many tables.
if (drupal_strlen($object->name) > 20) {
$name = drupal_substr($object->name, 0, 15) .'...';
} else {
$name = $object->name;
}

if (user_access('access user profiles')) {
$output = l($name, 'user/'. $object->uid, array('title' => t('View user profile.')));
} else {
$output = check_plain($name);
}

} else if ($object->name) {
// Sometimes modules display content composed by people who are
// not registered members of the site (e.g. mailing list or news
// aggregator modules). This clause enables modules to display
// the true author of the content.
if ($object->homepage) {
$output = l($object->name, $object->homepage);
} else {
$output = check_plain($object->name);
}

$output .= ' ('. t('not verified') .')';

} else {
$output = variable_get('anonymous', t('Anonymous'));
}
return $output;
}

?>

The theme_username function found in theme.inc

4. In your template.php file rename the theme_username function to phptemplate_username and save the file. This puts our template.php file in control of the theme_username function and completely bypasses the theme.inc version of the function.

Before

<?php
function theme_username($object) {
?>

After

<?php
function phptemplate_username($object) {
?>

5. We can now make any changes to the function we desire and all at theme level so we’re not messing with any modules or themes.
So let’s go ahead and add the users user ID after their username by modifying the last line of the phptemplate_username function to look like so:

<?php
$output .= '('. $object->uid .')';
return $output;
}
?>

So your final phptemplate_username function should look like this:

<?php
function phptemplate_username($object) {

if ($object->uid && $object->name) {
// Shorten the name when it is too long or it will break many tables.
if (drupal_strlen($object->name) > 20) {
$name = drupal_substr($object->name, 0, 15) .'...';
} else {
$name = $object->name;
}

if (user_access('access user profiles')) {
$output = l($name, 'user/'. $object->uid, array('title' => t('View user profile.')));
} else {
$output = check_plain($name);
}
} else if ($object->name) {
// Sometimes modules display content composed by people who are
// not registered members of the site (e.g. mailing list or news
// aggregator modules). This clause enables modules to display
// the true author of the content.
if ($object->homepage) {
$output = l($object->name, $object->homepage);
} else {
$output = check_plain($object->name);
}
$output .= ' ('. t('not verified') .')';
} else {
$output = variable_get('anonymous', t('Anonymous'));
}

$output .= ' ('. $object->uid .')';
return $output;
}
?>

6. Save the template.php file and as you should see something similar to the image below. Et viola you’ve just do your first theme override, pretty simple wasn’t it.