1. drupal
    1. 5
    2. 6
    3. 7
    4. 8
5 – 6 theme()
7 – 8 theme($hook, $variables = array())

Generates themed output.

All requests for themed output must go through this function. It examines the request and routes it to the appropriate theme function or template, by checking the theme registry.

The first argument to this function is the name of the theme hook. For instance, to theme a table, the theme hook name is 'table'. By default, this theme hook could be implemented by a function called 'theme_table' or a template file called 'table.tpl.php', but hook_theme() can override the default function or template name.

If the implementation is a template file, several functions are called before the template file is invoked, to modify the $variables array. These fall into the "preprocessing" phase and the "processing" phase, and are executed (if they exist), in the following order (note that in the following list, HOOK indicates the theme hook name, MODULE indicates a module name, THEME indicates a theme name, and ENGINE indicates a theme engine name):

  • template_preprocess(&$variables, $hook): Creates a default set of variables for all theme hooks.
  • template_preprocess_HOOK(&$variables): Should be implemented by the module that registers the theme hook, to set up default variables.
  • MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all implementing modules.
  • MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on all implementing modules, so that modules that didn't define the theme hook can alter the variables.
  • ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to set necessary variables for all theme hooks.
  • ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set necessary variables for the particular theme hook.
  • THEME_preprocess(&$variables, $hook): Allows the theme to set necessary variables for all theme hooks.
  • THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary variables specific to the particular theme hook.
  • template_process(&$variables, $hook): Creates a default set of variables for all theme hooks.
  • template_process_HOOK(&$variables): This is the first processor specific to the theme hook; it should be implemented by the module that registers it.
  • MODULE_process(&$variables, $hook): hook_process() is invoked on all implementing modules.
  • MODULE_process_HOOK(&$variables): hook_process_HOOK() is invoked on on all implementing modules, so that modules that didn't define the theme hook can alter the variables.
  • ENGINE_engine_process(&$variables, $hook): Allows the theme engine to set necessary variables for all theme hooks.
  • ENGINE_engine_process_HOOK(&$variables): Allows the theme engine to set necessary variables for the particular theme hook.
  • ENGINE_process(&$variables, $hook): Allows the theme engine to process the variables.
  • ENGINE_process_HOOK(&$variables): Allows the theme engine to process the variables specific to the theme hook.
  • THEME_process(&$variables, $hook): Allows the theme to process the variables.
  • THEME_process_HOOK(&$variables): Allows the theme to process the variables specific to the theme hook.

If the implementation is a function, only the theme-hook-specific preprocess and process functions (the ones ending in _HOOK) are called from the list above. This is because theme hooks with function implementations need to be fast, and calling the non-theme-hook-specific preprocess and process functions for them would incur a noticeable performance penalty.

There are two special variables that these preprocess and process functions can set: 'theme_hook_suggestion' and 'theme_hook_suggestions'. These will be merged together to form a list of 'suggested' alternate theme hooks to use, in reverse order of priority. theme_hook_suggestion will always be a higher priority than items in theme_hook_suggestions. theme() will use the highest priority implementation that exists. If none exists, theme() will use the implementation for the theme hook it was called with. These suggestions are similar to and are used for similar reasons as calling theme() with an array as the $hook parameter (see below). The difference is whether the suggestions are determined by the code that calls theme() or by a preprocess or process function.


$hook The name of the theme hook to call. If the name contains a double-underscore ('__') and there isn't an implementation for the full name, the part before the '__' is checked. This allows a fallback to a more generic implementation. For example, if theme('links__node', ...) is called, but there is no implementation of that theme hook, then the 'links' implementation is used. This process is iterative, so if theme('links__contextual__node', ...) is called, theme() checks for the following implementations, and uses the first one that exists:

  • links__contextual__node
  • links__contextual
  • links

This allows themes to create specific theme implementations for named objects and contexts of otherwise generic theme hooks. The $hook parameter may also be an array, in which case the first theme hook that has an implementation is used. This allows for the code that calls theme() to explicitly specify the fallback order in a situation where using the '__' convention is not desired or is insufficient.

$variables An associative array of variables to merge with defaults from the theme registry, pass to preprocess and process functions for modification, and finally, pass to the function or template implementing the theme hook. Alternatively, this can be a renderable array, in which case, its properties are mapped to variables expected by the theme hook implementations.

Return value

An HTML string representing the themed output.

▾ 221 functions call theme()

aggregator_aggregator_parse in modules/aggregator/
Implements hook_aggregator_parse().
aggregator_block_view in modules/aggregator/aggregator.module
Implements hook_block_view().
aggregator_categorize_items in modules/aggregator/
Form builder; build the page list form.
aggregator_page_categories in modules/aggregator/
Menu callback; displays all the categories used by the aggregator.
aggregator_page_opml in modules/aggregator/
Menu callback; generates an OPML representation of all feeds.
aggregator_page_rss in modules/aggregator/
Menu callback; generate an RSS 0.92 feed of aggregator items or categories.
aggregator_page_source in modules/aggregator/
Menu callback; displays all the items captured from a particular feed.
aggregator_page_sources in modules/aggregator/
Menu callback; displays all the feeds used by the aggregator.
aggregator_view in modules/aggregator/
Displays the aggregator administration page.
ajax_prepare_response in includes/
Converts the return value of a page callback into an Ajax commands array.
BlogTestCase::verifyBlogs in modules/blog/blog.test
Verify the logged in user has the desired access to the various blog nodes.
blog_page_user in modules/blog/
Menu callback; displays a Drupal page containing recent blog entries of a given user.
book_admin_overview in modules/book/
Returns an administrative overview of all books.
book_block_view in modules/book/book.module
Implements hook_block_view().
book_export_html in modules/book/
This function is called by book_export() to generate HTML for export.
book_node_export in modules/book/book.module
Generates printer-friendly HTML for a node.
book_node_view in modules/book/book.module
Implements hook_node_view().
book_render in modules/book/
Menu callback; prints a listing of all books.
comment_admin_overview in modules/comment/
Form builder for the comment overview administration form.
comment_block_view in modules/comment/comment.module
Implements hook_block_view().
comment_form in modules/comment/comment.module
Generate the basic commenting form, for appending to a node or display on a separate page.
comment_links in modules/comment/comment.module
Helper function, build links for an individual comment.
comment_node_view in modules/comment/comment.module
Implements hook_node_view().
contact_personal_form in modules/contact/
Form builder; the personal contact form.
dashboard_show_disabled in modules/dashboard/dashboard.module
Ajax callback to show disabled blocks in the dashboard customization mode.
dblog_event in modules/dblog/
Menu callback; displays details about a log message.
dblog_overview in modules/dblog/
Menu callback; displays a listing of log messages.
dblog_top in modules/dblog/
Menu callback; generic function to display a page of the most frequent events.
dbtng_example_advanced_list in examples/dbtng_example/dbtng_example.module
Render a filtered list of entries in the database.
dbtng_example_list in examples/dbtng_example/dbtng_example.module
Render a list of entries in the database.
drupal_add_feed in includes/
Add a feed URL for the current page.
drupal_deliver_html_page in includes/
Package and send the result of a page callback to the browser as HTML.
drupal_get_js in includes/
Returns a themed presentation of all JavaScript code for the current page.
drupal_render in includes/
Renders HTML given a structured array tree.
field_help in modules/field/field.module
Implements hook_help().
field_ui_fields_list in modules/field_ui/
Menu callback; lists all defined fields for quick reference.
field_ui_inactive_message in modules/field_ui/
Helper function to display a message about inactive fields.
field_ui_table_pre_render in modules/field_ui/
Pre-render callback for field_ui_table elements.
FileFieldDisplayTestCase::testNodeDisplay in modules/file/tests/file.test
Test normal formatter display on node display.
file_ajax_upload in modules/file/file.module
Menu callback; Shared Ajax callback for file uploads and deletions.
file_field_widget_form in modules/file/
Implements hook_field_widget_form().
file_managed_file_process in modules/file/file.module
Process function to expand the managed_file element type.
file_save_upload in includes/
Saves a file upload to a new location.
filter_tips_long in modules/filter/
Menu callback; show a page with long filter tips.
ForumTestCase::verifyForums in modules/forum/forum.test
Verify the logged in user has access to a forum nodes.
ForumTestCase::verifyForumView in modules/forum/forum.test
Verify display of forum page.
forum_help in modules/forum/forum.module
Implements hook_help().
forum_page in modules/forum/
Menu callback; prints a forum listing.
garland_preprocess_page in themes/garland/template.php
Override or insert variables into the page template.
help_page in modules/help/
Menu callback; prints a page listing general help for a module.
hook_ajax_render_alter in modules/system/system.api.php
Alter the commands that are sent to the user through the Ajax framework.
hook_process in modules/system/theme.api.php
Process theme variables.
hook_search_execute in modules/search/search.api.php
Execute a search for a set of key words.
hook_search_page in modules/search/search.api.php
Override the rendering of search results.
hook_view in modules/node/node.api.php
Display a node.
ImageFieldDisplayTestCase::testImageFieldDefaultImage in modules/image/image.test
Test use of a default image with an image field.
ImageFieldDisplayTestCase::testImageFieldSettings in modules/image/image.test
Tests for image field settings.
ImageFieldDisplayTestCase::_testImageFieldFormatters in modules/image/image.test
Test image formatters on node display.
image_example_style_form in examples/image_example/
Form for uploading and displaying an image using selected style.
image_field_widget_form in modules/image/
Implements hook_field_widget_form().
image_field_widget_process in modules/image/
An element #process callback for the image_image field type.
image_style_form in modules/image/
Form builder; Edit an image style name and effects order.
image_style_list in modules/image/
Menu callback; Listing of all current image styles.
install_display_output in includes/
Displays themed installer output and ends the page request.
install_verify_requirements in includes/
Installation task; verify the requirements for installing Drupal.
l in includes/
Formats an internal or external URL link as an HTML anchor tag.
locale_block_view in modules/locale/locale.module
Implements hook_block_view().
locale_date_format_language_overview_page in modules/locale/
Display edit date format links for each language.
locale_translate_overview_screen in modules/locale/
Overview screen for translations.
menu_overview_page in modules/menu/
Menu callback which shows an overview page of all the custom menus and their descriptions.
nodeapi_example_node_view in examples/nodeapi_example/nodeapi_example.module
Implements hook_view().
node_access_example_private_node_listing in examples/node_access_example/node_access_example.module
Our hook_menu() page callback function.
node_add_page in modules/node/
node_admin_nodes in modules/node/
Form builder: Builds the node administration overview.
node_block_view in modules/node/node.module
Implements hook_block_view().
node_example_field_formatter_view in examples/node_example/node_example.module
Implements hook_field_formatter_view().
node_overview_types in modules/node/
Displays the content type admin overview page.
node_page_default in modules/node/node.module
Menu callback; Generate a listing of promoted nodes.
node_preview in modules/node/
Generate a node preview.
node_revision_overview in modules/node/
Generate an overview table of older revisions of a node.
node_search_execute in modules/node/node.module
Implements hook_search_execute().
poll_page in modules/poll/
Menu callback to provide a simple list of all polls available.
poll_view_results in modules/poll/poll.module
Generates a graphical representation of the results of a poll.
poll_votes in modules/poll/
Callback for the 'votes' tab for polls you can see other votes on
profile_block_view in modules/profile/profile.module
Implements hook_block_view().
profile_browse in modules/profile/
Menu callback; display a list of user information.
queue_example_add_remove_form in examples/queue_example/queue_example.module
Provides an interface to add items to the queue, to retrieve (claim) an item from the head of the queue, and to claim and delete. Also allows the user to run cron manually, so that claimed items can be released.
rdf_process in modules/rdf/rdf.module
Template process function for adding extra tags to hold RDFa attributes.
search_extra_type_search_page in modules/search/tests/search_extra_type.module
Implements hook_search_page().
seven_tablesort_indicator in themes/seven/template.php
Override of theme_tablesort_indicator().
shortcut_set_admin in modules/shortcut/
Menu page callback: builds the page for administering shortcut sets.
simpletest_result_status_image in modules/simpletest/
Get the appropriate image for the status.
statistics_access_log in modules/statistics/
Menu callback; Displays recent page accesses.
statistics_node_tracker in modules/statistics/
statistics_recent_hits in modules/statistics/
Menu callback; presents the "recent hits" page.
statistics_top_visitors in modules/statistics/
Menu callback; presents the "top visitors" page.
system_actions_manage in modules/system/
Menu callback; Displays an overview of available and configured actions.
system_admin_config_page in modules/system/
Menu callback; Provide the administration overview page.
system_admin_index in modules/system/
Menu callback; prints a listing of admin tasks, organized by module.
system_admin_menu_block_page in modules/system/
Provide a single block from the administration menu as a page.
system_block_view in modules/system/system.module
Implements hook_block_view().
system_modules_confirm_form in modules/system/
Display confirmation form for required modules.
system_modules_uninstall_confirm_form in modules/system/
Confirm uninstall of selected modules.
system_requirements in modules/system/system.install
Test and report Drupal installation requirements.
system_settings_overview in modules/system/
Menu callback; displays a module's settings page.
system_status in modules/system/
Menu callback: displays the site status report. Can also be used as a pure check.
system_themes_page in modules/system/
Menu callback; displays a listing of all themes.
tablesort_header in includes/
Format a column header.
template_preprocess_aggregator_feed_source in modules/aggregator/
Process variables for aggregator-feed-source.tpl.php.
template_preprocess_aggregator_summary_items in modules/aggregator/
Process variables for aggregator-summary-items.tpl.php.
template_preprocess_aggregator_wrapper in modules/aggregator/
Process variables for aggregator-wrapper.tpl.php.
template_preprocess_comment in modules/comment/comment.module
Process variables for comment.tpl.php.
template_preprocess_forums in modules/forum/forum.module
Process variables for forums.tpl.php
template_preprocess_forum_list in modules/forum/forum.module
Process variables to format a forum listing.
template_preprocess_forum_submitted in modules/forum/forum.module
Process variables to format submission info for display in the forum list and topic list.
template_preprocess_forum_topic_list in modules/forum/forum.module
Preprocess variables to format the topic listing.
template_preprocess_maintenance_page in includes/
The variables array generated here is a mirror of template_preprocess_page(). This preprocessor will run its course when theme_maintenance_page() is invoked.
template_preprocess_node in modules/node/node.module
Process variables for node.tpl.php
template_preprocess_poll_results in modules/poll/poll.module
Preprocess the poll_results theme hook.
template_preprocess_profile_block in modules/profile/profile.module
Process variables for profile-block.tpl.php.
template_preprocess_profile_listing in modules/profile/profile.module
Process variables for profile-listing.tpl.php.
template_preprocess_search_results in modules/search/
Process variables for search-results.tpl.php.
template_preprocess_user_picture in modules/user/user.module
Process variables for user-picture.tpl.php.
template_process_page in includes/
Process variables for page.tpl.php
ThemeItemListUnitTest::testNestedList in modules/simpletest/tests/theme.test
Test nested list rendering.
ThemeTableUnitTest::testThemeTableNoStickyHeaders in modules/simpletest/tests/theme.test
If $sticky is FALSE, no tableheader.js should be included.
ThemeTableUnitTest::testThemeTableStickyHeaders in modules/simpletest/tests/theme.test
Tableheader.js provides 'sticky' table headers, and is included by default.
ThemeTableUnitTest::testThemeTableWithEmptyMessage in modules/simpletest/tests/theme.test
Tests that the table header is printed correctly even if there are no rows, and that the empty text is displayed correctly.
theme_admin_page in modules/system/
Returns HTML for an administrative page.
theme_aggregator_categorize_items in modules/aggregator/
Returns HTML for the aggregator page list form for assigning categories.
theme_authorize_report in includes/
Returns HTML for a report of the results from an operation run via authorize.php.
theme_book_admin_table in modules/book/
Returns HTML for a book administration form.
theme_comment_block in modules/comment/comment.module
Returns HTML for a list of recent comments to be displayed in the comment block.
theme_dashboard_disabled_blocks in modules/dashboard/dashboard.module
Returns HTML for a set of disabled blocks, for display in dashboard customization mode.
theme_exposed_filters in modules/system/system.module
Returns HTML for an exposed filter form.
theme_feed_icon in includes/
Returns HTML for a feed icon.
theme_field_multiple_value_form in modules/field/
Returns HTML for an individual form element.
theme_field_ui_table in modules/field_ui/
Returns HTML for Field UI overview tables.
theme_file_formatter_table in modules/file/
Returns HTML for a file attachments table.
theme_file_link in modules/file/file.module
Returns HTML for a link to a file.
theme_file_widget_multiple in modules/file/
Returns HTML for a group of file upload widgets.
theme_filter_admin_format_filter_order in modules/filter/
Returns HTML for a text format's filter order form.
theme_filter_admin_overview in modules/filter/
Returns HTML for the text format administration overview form.
theme_filter_guidelines in modules/filter/filter.module
Returns HTML for guidelines for a text format.
theme_form_element in includes/
Returns HTML for a form element.
theme_form_element_label in includes/
Returns HTML for a form element label and required marker.
theme_form_example_checkbox in examples/form_example/
Themes a custom checkbox.
theme_form_example_inline_form_element in examples/form_example/
Formats child form elements as inline elements.
theme_image_anchor in modules/image/
Returns HTML for a 3x3 grid of checkboxes for image anchors.
theme_image_crop_summary in modules/image/
Returns HTML for a summary of an image crop effect.
theme_image_example_image in examples/image_example/
Theme function displays an image rendered using the specified style.
theme_image_formatter in modules/image/
Returns HTML for an image field formatter.
theme_image_scale_summary in modules/image/
Returns HTML for a summary of an image scale effect.
theme_image_style in modules/image/image.module
Returns HTML for an image using a specific image style.
theme_image_style_effects in modules/image/
Returns HTML for a listing of the effects within a specific image style.
theme_image_style_list in modules/image/
Returns HTML for the page containing the list of image styles.
theme_image_style_preview in modules/image/
Returns HTML for a preview of an image style.
theme_install_page in includes/
Returns HTML for the installation page.
theme_locale_date_format_form in modules/locale/
Returns HTML for a locale date format form.
theme_locale_languages_configure_form in modules/locale/
Returns HTML for a language configuration form.
theme_locale_languages_overview_form in modules/locale/
Returns HTML for the language overview form.
theme_menu_overview_form in modules/menu/
Returns HTML for the menu overview form into a table.
theme_node_recent_block in modules/node/node.module
Returns HTML for a list of recent content.
theme_node_recent_content in modules/node/node.module
Returns HTML for a recent node to be displayed in the recent content block.
theme_node_search_admin in modules/node/node.module
Returns HTML for the content ranking part of the search settings admin page.
theme_pager in includes/
Returns HTML for a query pager.
theme_pager_first in includes/
Returns HTML for the "first page" link in a query pager.
theme_pager_last in includes/
Returns HTML for the "last page" link in query pager.
theme_pager_next in includes/
Returns HTML for the "next page" link in a query pager.
theme_pager_previous in includes/
Returns HTML for the "previous page" link in a query pager.
theme_poll_choices in modules/poll/poll.module
Returns HTML for an admin poll form for choices.
theme_profile_admin_overview in modules/profile/
Returns HTML for the profile field overview form into a drag and drop enabled table.
theme_queue_items in examples/queue_example/queue_example.module
Themes the queue display.
theme_shortcut_set_customize in modules/shortcut/
Returns HTML for a shortcut set customization form.
theme_simpletest_test_table in modules/simpletest/
Returns HTML for a test list generated by simpletest_test_form() into a table.
theme_submit in includes/
Returns HTML for a submit button form element.
theme_system_admin_index in modules/system/
Returns HTML for the output of the dashboard page.
theme_system_date_time_settings in modules/system/
Returns HTML for the date settings form.
theme_system_modules_fieldset in modules/system/
Returns HTML for the modules form.
theme_system_modules_uninstall in modules/system/
Returns HTML for a table of currently disabled modules.
theme_system_themes_page in modules/system/
Returns HTML for the Appearance page.
theme_tableselect in includes/
Returns HTML for a table with radio buttons or checkboxes.
theme_tablesort_indicator in includes/
Returns HTML for a sort icon.
theme_taxonomy_overview_terms in modules/taxonomy/
Returns HTML for a terms overview form as a sortable list of terms.
theme_taxonomy_overview_vocabularies in modules/taxonomy/
Returns HTML for the vocabulary overview form as a sortable list of vocabularies.
theme_test_init in modules/simpletest/tests/theme_test.module
Implements hook_init().
theme_theming_example_list in examples/theming_example/theming_example.module
Theming a simple list.
theme_trigger_display in modules/trigger/
Returns HTML for the form showing actions assigned to a trigger.
theme_update_manager_update_form in modules/update/
Returns HTML for the first page in the update manager wizard to select projects.
theme_update_page in includes/
Returns HTML for the update page.
theme_update_report in modules/update/
Returns HTML for the project status report.
theme_update_version in modules/update/
Returns HTML for the version display of a project.
theme_user_admin_permissions in modules/user/
Returns HTML for the administer permissions page.
theme_user_admin_roles in modules/user/
Returns HTML for the role order and new role form.
theme_user_list in modules/user/user.module
Returns HTML for a list of users.
tracker_page in modules/tracker/
Menu callback; prints a listing of active nodes on the site.
update_check_requirements in ./update.php
Check update requirements and report any errors.
update_manager_download_batch_finished in modules/update/
Batch callback invoked when the download batch is completed.
update_manager_update_form in modules/update/
Build the form for the update manager page to update existing projects.
update_results_page in ./update.php
update_script_selection_form in ./update.php
update_status in modules/update/
Menu callback. Generate a page about the update status of projects.
update_task_list in ./update.php
Add the update task list to the current page.
user_account_form in modules/user/user.module
Helper function to add default user account fields to user registration and edit form.
user_admin_account in modules/user/
Form builder; User administration page.
user_admin_permissions in modules/user/
Menu callback: administer permissions.
user_block_view in modules/user/user.module
Implements hook_block_view().
user_login_block in modules/user/user.module
user_user_view in modules/user/user.module
Implements hook_user_view().
xmlrpc_example_info in examples/xmlrpc_example/xmlrpc_example.module
A simple landing-page information function.
_aggregator_page_list in modules/aggregator/
Prints an aggregator page listing a number of feed items.
_batch_progress_page_nojs in includes/
Output a batch processing page without JavaScript support.
_color_theme_select_form_alter in modules/color/color.module
Helper for hook_form_FORM_ID_alter() implementations.
_drupal_log_error in includes/
Log a PHP error or exception, display an error page in fatal cases.
_filter_html_tips in modules/filter/filter.module
Filter tips callback for HTML filter.
_locale_translate_seek in includes/
Perform a string search and display results in a table
_node_mass_update_batch_finished in modules/node/
Node Mass Update Batch 'finished' callback.
_options_get_options in modules/field/modules/options/options.module
Collects the options for a field.
_simpletest_batch_operation in modules/simpletest/simpletest.module
Batch operation callback.
_system_modules_build_row in modules/system/
Build a table row for the system modules page.
_theme_test_suggestion in modules/simpletest/tests/theme_test.module
Page callback, calls a theme hook suggestion.


includes/, line 762

function theme($hook, $variables = array()) {
  static $hooks = NULL;

  // If called before all modules are loaded, we do not necessarily have a full
  // theme registry to work with, and therefore cannot process the theme
  // request properly. See also _theme_load_registry().
  if (!module_load_all(NULL) && !defined('MAINTENANCE_MODE')) {
    throw new Exception(t('theme() may not be called until all modules are loaded.'));

  if (!isset($hooks)) {
    $hooks = theme_get_registry();

  // If an array of hook candidates were passed, use the first one that has an
  // implementation.
  if (is_array($hook)) {
    foreach ($hook as $candidate) {
      if (isset($hooks[$candidate])) {
    $hook = $candidate;

  // If there's no implementation, check for more generic fallbacks. If there's
  // still no implementation, log an error and return an empty string.
  if (!isset($hooks[$hook])) {
    // Iteratively strip everything after the last '__' delimiter, until an
    // implementation is found.
    while ($pos = strrpos($hook, '__')) {
      $hook = substr($hook, 0, $pos);
      if (isset($hooks[$hook])) {
    if (!isset($hooks[$hook])) {
      // Only log a message when not trying theme suggestions ($hook being an
      // array).
      if (!isset($candidate)) {
        watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING);
      return '';

  $info = $hooks[$hook];
  global $theme_path;
  $temp = $theme_path;
  // point path_to_theme() to the currently used theme path:
  $theme_path = $info['theme path'];

  // Include a file if the theme function or variable processor is held elsewhere.
  if (!empty($info['includes'])) {
    foreach ($info['includes'] as $include_file) {
      include_once DRUPAL_ROOT . '/' . $include_file;

  // If a renderable array is passed as $variables, then set $variables to
  // the arguments expected by the theme function.
  if (isset($variables['#theme']) || isset($variables['#theme_wrappers'])) {
    $element = $variables;
    $variables = array();
    if (isset($info['variables'])) {
      foreach (array_keys($info['variables']) as $name) {
        if (isset($element["#$name"])) {
          $variables[$name] = $element["#$name"];
    else {
      $variables[$info['render element']] = $element;

  // Merge in argument defaults.
  if (!empty($info['variables'])) {
    $variables += $info['variables'];
  elseif (!empty($info['render element'])) {
    $variables += array($info['render element'] => array());

  // Invoke the variable processors, if any. The processors may specify
  // alternate suggestions for which hook's template/function to use. If the
  // hook is a suggestion of a base hook, invoke the variable processors of
  // the base hook, but retain the suggestion as a high priority suggestion to
  // be used unless overridden by a variable processor function.
  if (isset($info['base hook'])) {
    $base_hook = $info['base hook'];
    $base_hook_info = $hooks[$base_hook];
    if (isset($base_hook_info['preprocess functions']) || isset($base_hook_info['process functions'])) {
      $variables['theme_hook_suggestion'] = $hook;
      $hook = $base_hook;
      $info = $base_hook_info;
  if (isset($info['preprocess functions']) || isset($info['process functions'])) {
    $variables['theme_hook_suggestions'] = array();
    foreach (array('preprocess functions', 'process functions') as $phase) {
      if (!empty($info[$phase])) {
        foreach ($info[$phase] as $processor_function) {
          if (function_exists($processor_function)) {
            // We don't want a poorly behaved process function changing $hook.
            $hook_clone = $hook;
            $processor_function($variables, $hook_clone);
    // If the preprocess/process functions specified hook suggestions, and the
    // suggestion exists in the theme registry, use it instead of the hook that
    // theme() was called with. This allows the preprocess/process step to
    // route to a more specific theme hook. For example, a function may call
    // theme('node', ...), but a preprocess function can add 'node__article' as
    // a suggestion, enabling a theme to have an alternate template file for
    // article nodes. Suggestions are checked in the following order:
    // - The 'theme_hook_suggestion' variable is checked first. It overrides
//   all others.
    // - The 'theme_hook_suggestions' variable is checked in FILO order, so the
//   last suggestion added to the array takes precedence over suggestions
//   added earlier.
    $suggestions = array();
    if (!empty($variables['theme_hook_suggestions'])) {
      $suggestions = $variables['theme_hook_suggestions'];
    if (!empty($variables['theme_hook_suggestion'])) {
      $suggestions[] = $variables['theme_hook_suggestion'];
    foreach (array_reverse($suggestions) as $suggestion) {
      if (isset($hooks[$suggestion])) {
        $info = $hooks[$suggestion];

  // Generate the output using either a function or a template.
  $output = '';
  if (isset($info['function'])) {
    if (function_exists($info['function'])) {
      $output = $info['function']($variables);
  else {
    // Default render function and extension.
    $render_function = 'theme_render_template';
    $extension = '.tpl.php';

    // The theme engine may use a different extension and a different renderer.
    global $theme_engine;
    if (isset($theme_engine)) {
      if ($info['type'] != 'module') {
        if (function_exists($theme_engine . '_render_template')) {
          $render_function = $theme_engine . '_render_template';
        $extension_function = $theme_engine . '_extension';
        if (function_exists($extension_function)) {
          $extension = $extension_function();

    // In some cases, a template implementation may not have had
    // template_preprocess() run (for example, if the default implementation is
    // a function, but a template overrides that default implementation). In
    // these cases, a template should still be able to expect to have access to
    // the variables provided by template_preprocess(), so we add them here if
    // they don't already exist. We don't want to run template_preprocess()
    // twice (it would be inefficient and mess up zebra striping), so we use the
    // 'directory' variable to determine if it has already run, which while not
    // completely intuitive, is reasonably safe, and allows us to save on the
    // overhead of adding some new variable to track that.
    if (!isset($variables['directory'])) {
      $default_template_variables = array();
      template_preprocess($default_template_variables, $hook);
      $variables += $default_template_variables;

    // Render the output using the template file.
    $template_file = $info['template'] . $extension;
    if (isset($info['path'])) {
      $template_file = $info['path'] . '/' . $template_file;
    $output = $render_function($template_file, $variables);

  // restore path_to_theme()
  $theme_path = $temp;
  return $output;