Overriding module functionality in Drupal

by John McGeechan

Synopsis

Sometimes it is necessary to override the functionality of a particular module. You may wish to to customize some functionality but without hacking the core code of the module.

How do you do this ?

There are several ways, here is just one.....

Assumptions

This article relates to Drupal 5.x, it may also be relevant to other versions of Drupal

Background

Some functionality is easily overriden, all code that uses the 'theme' function for example (and all well written modules should use this) can be overriden by adding extra functions to template.php. Drupal's theming system is similar to the hook system and it looks actively for override functions before determing which function to call. How this works is beyond the scope of this article, but for more information try here.  

Some functions however do not go through theming, overriding these is still achievable but can be much more complex  depending on what is required.

Solution

 

As an example, the term view of the taxonomy module does not include any description of the term by default, it simply lists  all articles related to a term. To change this behaviour, the callback defined by the taxonomy module in the hook_menu can be overriden.

Amongst the callbacks defined by the taxonomy module in the hook_menu is the term view.....

/**
 * Implementation of hook_menu(). (taxonomy version 1.1)
 */
function taxonomy_menu($may_cache) {

$items = array();

....

$items[] = array('path' => 'taxonomy/term',
'title' => t('Taxonomy term'),
'callback' => 'taxonomy_term_page',
'access' => user_access('access content'),
'type' => MENU_CALLBACK);

....

}

As can be seen the term view maps to the function 'taxonomy_term_page' and a quick glance at this function reveals that no term description is displayed before the articles are listed.

To override this create a new module called 'custom' or something similar, create an info and a module version of the file, something similar to this

custom.info should look similar to this...

; $Id$
name = custom module
description = Customize specifics for the site
package = customize
version = "$Name$"

 custom.module should look like this...

<?php
function custom_menu($may_cache = null)
{

  $items = array();
  if (!$may_cache) {
   
    // override logic for taxonomy term display
    $items[] = array('path' => 'taxonomy/term',
      'title' => t('Taxonomy term'),
      'callback' => 'custom_taxonomy_term_override',
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK);

  }
  return $items;

}

?> 

Note that the module again uses the hook_menu and that the module also defines the same callback path, however it defines the callback to a function we have not yet defined ( custom_taxonomy_term_override). Let's do that now...

function custom_taxonomy_term_override($str_tids = '', $depth = 0, $op = 'page')
{
 
  // if not a page default to base taxonomy logic
  if ($op != 'page') {
      return taxonomy_term_page($str_tids,$depth,$op) ;
  }   
 
  // must be a page, get description before calling base taxonomy logic
  $result = db_query(db_rewrite_sql('SELECT t.description FROM {term_data} t WHERE t.tid = %d', 't', 'tid'), $str_tids);
  $term = db_fetch_object($result);
  return $term->description . taxonomy_term_page($str_tids,$depth,$op);
 
}

Note that the signature of the function is exactly the same as that of the 'taxonomy_term_page' function in the taxonomy module. Note that if the operation is not a page ie rss, then it simply relinquishes control back to the taxonomy_term_page function. If this is a page operation then the SQL to select the term name is performed and this is tagged to the front of the call to  taxonomy_term_page. This now in theory is a module that will override the default behaviour for displaying term articles.

The next step is to enable the module using Administer > Site Building > Modules . Note that before you use this module you may have to update it's weight on the system table. This is to ensure that the callback of your module is given a higher priority than the taxonomy module....

update system set weight = -99 where name = 'custom';    

 Now any term descriptions that are entered in the term description field (Administer » Content management » Categories) should now appear above the list of articles.

Things to note

  • This override module or custom module can be used to add as many ovverrides for as many different modules as are necessary
  • The return value of your function should always be the same type as that returned by the function you are overriding. So if taxonomy_term_page had returned an array rather than a string, then the override function should do the same
  • It may get quite complex to override the particular functionality that you need to change. This may mean adding potentially several ovverride functions
  • if a module is upgraded it may be necessary to change this override module. This is still a better option than hacking the module itself

 

 

 

 

 

 

 

Great post man! I was

Great post man! I was looking for something like this.

function without menu hook

Hi,
this is the first manual, that makes sence. But can you tell me, if it is possible to override function, that not depends on menu hook?. Just a function in some module that is used in other functions to load something for example.

Thank you and have a nice day
Karel

Post new comment

By submitting this form, you accept the Mollom privacy policy.