Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.598 diff -u -p -r1.598 theme.inc --- includes/theme.inc 19 May 2010 19:22:24 -0000 1.598 +++ includes/theme.inc 5 Jun 2010 23:51:01 -0000 @@ -764,7 +764,7 @@ function theme($hook, $variables = array } } if (!isset($hooks[$hook])) { - watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING); + trigger_error(t('Theme key "@key" not found.', array('@key' => $hook))); return ''; } } @@ -866,6 +866,13 @@ function theme($hook, $variables = array if (function_exists($info['function'])) { $output = $info['function']($variables); } + else { + // If a function implementation is registered but doesn't exist, it's + // either due to a bug in a module or theme, or module or theme code has + // been updated without the theme registry being rebuilt. + trigger_error(t('Theme function "@function" not found.', array('@function' => $info['function']))); + $output = ''; + } } else { // Default render function and extension. @@ -908,6 +915,14 @@ function theme($hook, $variables = array $template_file = $info['path'] . '/' . $template_file; } $output = $render_function($template_file, $variables); + + // A successfully rendered template should always return a string (an empty + // string is valid). The template renderer can return literal FALSE to + // indicate an error (e.g., if the template file doesn't exist). + if ($output === FALSE) { + trigger_error(t('Theme template "@template" not found or cannot be rendered.', array('@template' => $template_file))); + $output = ''; + } } // restore path_to_theme() @@ -1217,7 +1232,14 @@ function theme_render_template($template extract($variables, EXTR_SKIP); // Extract the variables to a local namespace ob_start(); // Start output buffering include DRUPAL_ROOT . '/' . $template_file; // Include the template file - return ob_get_clean(); // End buffering and return its contents + $output = ob_get_clean(); // End buffering and get its contents + // We don't want to call file_exists() unnecessarily, but if nothing was + // rendered, it might be due to a missing template file, and we need to flag + // that as an error by returning FALSE. + if ($output === '' && !file_exists(DRUPAL_ROOT . '/' . $template_file)) { + $output = FALSE; + } + return $output; } /**