Drupal: Changing module behavior without changing the source code

For the project I’m currently working on, I’m not allowed to make any changes to third-party source code. Yes, I’ve pointed them to the GPL and Drupal FAQs about being legally allowed to make modifications to a system that will be hosted but not publicly discributed, without being required to contribute those changes back to the community. As much as I would like to release all the modifications back to the community, I also care about proper interpretation of the GPL. I suspect our project restrictions are a combination of wanting to be able to upgrade modules easily and erring on the safe side when it comes to the legal requirements of open source.

Anyway. If you’re trying to avoid making changes to third-party source code when you’re customizing your Drupal system, here are several ways you can alter the module’s behavior:

  • Hooks: Drupal has an extensive hook system allowing you to alter forms (hook_form_alter), node behavior (hook_nodeapi), user behavior (hook_user), and do other cool things. Read about the hooks in your version of Drupal, and see if any of those hooks can help you wrap code around what you want to modify.
  • Theme functions: Well-written Drupal modules use theme functions to make the HTML output easily customizable. Check the function you want Create a custom theme and override the functions in your template.php. For example, if you’re using the PHPTemplate engine, you can override a theme_foo_bar(…) method by defining a phptemplate_foo_bar(…) function in your template.php.
  • String overrides: If you want to change a displayed string and it’s wrapped in t(‘…’) calls (as it should be), use String Overrides to set up an English-to-English translation for that string. If you use the internationalization and localization features of Drupal, you don’t need String Overrides – just set up custom English translation for your site.
  • Menu overrides: Use this if the module outputs HTML directly, or if you want to change more of the functionality. In your custom module, you can define a menu item with the same path as a menu item defined by a different module. Copy the menu item definition from the other module, then change the callback function and the arguments to point to customized copies of the functions. If you do this, check the {system} table to make sure that your module has a greater weight than the module it’s overriding. You may have to duplicate a number of functions in order to get to the menu item you need to change.
  • String replacement: If you’re desperate, you can use string replacement on the page before it’s sent to the browser. Use this only in emergencies, as it’s ugly and it wastes all the processing time spent coming up with the string you’re going to replace.
  • Module replacement: If you’re absolutely desperate, make a copy of the module and change all the names so that you remember this is a customized module instead of something that you can cleanly update.

Your Drupal modifications are also under the GPL, so pay attention to the licensing terms. =)