summaryrefslogtreecommitdiff
path: root/includes/theme.inc
diff options
context:
space:
mode:
Diffstat (limited to 'includes/theme.inc')
-rw-r--r--includes/theme.inc49
1 files changed, 37 insertions, 12 deletions
diff --git a/includes/theme.inc b/includes/theme.inc
index 9c7b767bb..79a9732c8 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -737,12 +737,23 @@ function list_themes($refresh = FALSE) {
* the original registered function for the theme hook.
*
* @param $hook
- * The name of the theme function to call. May be an array, in which
- * case the first hook that actually has an implementation registered
- * will be used. This can be used to choose 'fallback' theme implementations,
- * so that if the specific theme hook isn't implemented anywhere, a more
- * generic one will be used. This can allow themes to create specific theme
- * implementations for named objects.
+ * 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 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 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 insufficient.
*
* @param $variables
* An associative array of variables to merge with defaults from the theme
@@ -772,9 +783,21 @@ function theme($hook, $variables = array()) {
$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])) {
- watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING);
- return '';
+ // 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])) {
+ break;
+ }
+ }
+ if (!isset($hooks[$hook])) {
+ watchdog('theme', 'Theme key "@key" not found.', array('@key' => $hook), WATCHDOG_WARNING);
+ return '';
+ }
}
$info = $hooks[$hook];
@@ -993,8 +1016,9 @@ function drupal_find_theme_functions($cache, $prefixes) {
foreach ($cache as $hook => $info) {
foreach ($prefixes as $prefix) {
- if (!empty($info['pattern'])) {
- $matches = preg_grep('/^' . $prefix . '_' . $info['pattern'] . '/', $functions['user']);
+ $pattern = isset($info['pattern']) ? $info['pattern'] : ($hook . '__');
+ if (!empty($pattern)) {
+ $matches = preg_grep('/^' . $prefix . '_' . $pattern . '/', $functions['user']);
if ($matches) {
foreach ($matches as $match) {
$new_hook = str_replace($prefix . '_', '', $match);
@@ -1091,10 +1115,11 @@ function drupal_find_theme_templates($cache, $extension, $path) {
$patterns = array_keys($files);
foreach ($cache as $hook => $info) {
- if (!empty($info['pattern'])) {
+ $pattern = isset($info['pattern']) ? $info['pattern'] : ($hook . '__');
+ if (!empty($pattern)) {
// Transform _ in pattern to - to match file naming scheme
// for the purposes of searching.
- $pattern = strtr($info['pattern'], '_', '-');
+ $pattern = strtr($pattern, '_', '-');
$matches = preg_grep('/^' . $pattern . '/', $patterns);
if ($matches) {