The theme registry for special cases

Last modified: August 23, 2009 - 15:37

You should be familiar with the purpose of the theme registry before continuing on this page. The instructions here will cover how to manually register a theming hook and explain how it can be manipulated.

The most common case for manually registering hooks are in forms. Form elements are themable but there is another dimension to how they are processed. There are the generic elements such as checkboxes, radio selects, submit button, drop down menus, etc. Each element is themable on its own and overriding them does not require manually registering the hooks associated with them. The extra dimension comes in with custom forms where each element is arranged in very specific ways. In some forms, they are already arranged, themed and registered. For these forms, manually registering is not required. The forms that are not explicitly themed will default to how form API renders them.

Registered form example:

Here's an example for two of the search forms registered by search.module, the search box and search block. Every form has a unique id associated with them. Registering the id's also serve as the theming hook. In this case, it is "search_theme_form" and "search_block_form".

<?php
function search_theme() {
  return array(
   
'search_theme_form' => array(
     
'arguments' => array('form' => NULL),
     
'template' => 'search-theme-form',
    ),
   
'search_block_form' => array(
     
'arguments' => array('form' => NULL),
     
'template' => 'search-block-form',
    ),
    ...
  );
}
?>

Form API passes control of its presentation along to the handler of the registered hook. In this example, it is registered with the type of template with its default arguments. The output can be altered easily from the theme since it was already registered as a template. Auto discovery of the hook only happens with existing theming hooks registered below the theming layer. (see image)

Registering an unregistered form:

There is another search form that is not registered. It is the form with the id of "search_form" used on the main search page. The data for the form is constructed in a function just like any other form but it leaves it up to form API to deal with the presentation based on its data structure.

To extend this so it can be overridden, you have to register it from your theme with hook_theme. Place the following inside your template.php file replacing the "drop" prefix with the name of your theme. The theming hook is the id of the form:

<?php
function drop_theme() {
  return array(
   
'search_form' => array(
     
'arguments' => array('form' => NULL),
    ),
  );
}
?>

Themed forms always have an argument of "form". Since the template was not specified, the hook will be seen as a theme function, not a template. The theme function has to have a matching prefix of the theme that registered it. phptemplate_* will not work. So, with the above entry, the theme function would look like this:

<?php
function drop_search_form($form) {
 
$advanced = '';
 
$simple = '';
  foreach (
element_children($form) as $element) {
    if (
$element == 'advanced') {
     
$advanced .= drupal_render($form[$element]);
    }
    else {
     
$simple .= drupal_render($form[$element]);
    }
  }
  return
$advanced . $simple;
}
?>

The only thing changed here is the positioning of the advanced search form.

  • Sub-themes overriding a form that was registered in its base theme does not have to manually re-register the form. Remember, the registering allows auto discovery for the layers above it and sub-themes are just another layer on top of base themes.
  • This may be more automated in future versions. The developers are aware of the burden it places on themers.

Manual manipulating

Manual manipulation of the theme registry is an advanced feature. You can read it by clicking the "Theme registry" in the block provided by devel module. It can also be returned with theme_get_registry.

to be continued...

There's an undocumented hook

Nick Lewis - March 7, 2008 - 21:58

There's an undocumented hook to alter the theme registry:

<?php

function hook_theme_registry_alter(&$vars) {
/* alter the array */
}
?>

Examples: http://shellmultimedia.com/articles/hookthemeregistryalter-advanced-temp...
Patch: http://drupal.org/node/180389
--
"I'm not concerned about all hell breaking loose, but that a PART of hell will break loose... it'll be much harder to detect." - George Carlin
--
Personal: http://www.nicklewis.org
Work: http://www.onnetworks.com

Although

dvessel - March 13, 2008 - 17:43

Although hook_theme_registry_alter should not be a concern to theme devs I'll link to it from here after I document it for a.d.o. That hook only applies to modules.

joon park
www.dvessel.com

For theme developers

JohnAlbin - May 13, 2008 - 21:42

Theme developers can modify the theme registry directly by implementing a HOOK_theme() function with a pass-by-reference param for $existing. i.e.

Instead of calling HOOK_theme like this:

<?php
function mytheme_theme($existing, $type, $theme, $path) {
// You can examine (but not modify) the theme cache in $existing
}
?>

Do this instead:

<?php
function mytheme_theme(&$existing, $type, $theme, $path) {
// Modify the theme cache directly by modifying $existing
}
?>

The HOOK_theme function wasn't intended to allow themes to modify the theme registry directly, but since HOOK_theme_registry_alter() only works for modules, there is no other way for a theme to achieve this.

  - John (JohnAlbin)

 
 

Drupal is a registered trademark of Dries Buytaert.