Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.471 diff -u -p -r1.471 theme.inc --- includes/theme.inc 4 Apr 2009 00:58:09 -0000 1.471 +++ includes/theme.inc 6 Apr 2009 09:32:04 -0000 @@ -304,72 +304,85 @@ function _theme_process_registry(&$cache include_once DRUPAL_ROOT . '/' . $info['path'] . '/' . $info['file']; } - if (isset($info['template']) && !isset($info['path'])) { - $result[$hook]['template'] = $path . '/' . $info['template']; - } // If 'arguments' have been defined previously, carry them forward. // This should happen if a theme overrides a Drupal defined theme // function, for example. if (!isset($info['arguments']) && isset($cache[$hook])) { $result[$hook]['arguments'] = $cache[$hook]['arguments']; } - // Likewise with theme paths. These are used for template naming suggestions. - // Theme implementations can occur in multiple paths. Suggestions should follow. - if (!isset($info['theme paths']) && isset($cache[$hook])) { - $result[$hook]['theme paths'] = $cache[$hook]['theme paths']; - } - // Check for sub-directories. - $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path; - - // Check for default _preprocess_ functions. Ensure arrayness. - if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) { - $info['preprocess functions'] = array(); - $prefixes = array(); - if ($type == 'module') { - // Default preprocessor prefix. - $prefixes[] = 'template'; - // Add all modules so they can intervene with their own preprocessors. This allows them - // to provide preprocess functions even if they are not the owner of the current hook. - $prefixes += module_list(); - } - elseif ($type == 'theme_engine' || $type == 'base_theme_engine') { - // Theme engines get an extra set that come before the normally named preprocessors. - $prefixes[] = $name . '_engine'; - // The theme engine also registers on behalf of the theme. The theme or engine name can be used. - $prefixes[] = $name; - $prefixes[] = $theme; - } - else { - // This applies when the theme manually registers their own preprocessors. - $prefixes[] = $name; - } - foreach ($prefixes as $prefix) { - if (function_exists($prefix . '_preprocess')) { - $info['preprocess functions'][] = $prefix . '_preprocess'; + // The following apply only to theming hooks implemented as templates. + if (isset($info['template'])) { + // Prepend the current theming path when none is set. + if (!isset($info['path'])) { + $result[$hook]['template'] = $path . '/' . $info['template']; + } + + // These are used for template naming suggestions. Theme implementations + // can occur in multiple paths. Suggestions should follow. + if (!isset($info['theme paths']) && isset($cache[$hook])) { + $result[$hook]['theme paths'] = $cache[$hook]['theme paths']; + } + // Check for sub-directories. + $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path; + + // Template functions work in two distinct phases with the process + // functions always being executed after the preprocess functions. + $template_phases = array( + 'preprocess functions' => 'preprocess', + 'process functions' => 'process', + ); + foreach ($template_phases as $phase_key => $template_phase) { + // Check for default _preprocess_ functions. Ensure arrayness. + if (!isset($info[$phase_key]) || !is_array($info[$phase_key])) { + $info[$phase_key] = array(); + $prefixes = array(); + if ($type == 'module') { + // Default preprocessor prefix. + $prefixes[] = 'template'; + // Add all modules so they can intervene with their own preprocessors. This allows them + // to provide preprocess functions even if they are not the owner of the current hook. + $prefixes += module_list(); + } + elseif ($type == 'theme_engine' || $type == 'base_theme_engine') { + // Theme engines get an extra set that come before the normally named preprocessors. + $prefixes[] = $name . '_engine'; + // The theme engine also registers on behalf of the theme. The theme or engine name can be used. + $prefixes[] = $name; + $prefixes[] = $theme; + } + else { + // This applies when the theme manually registers their own preprocessors. + $prefixes[] = $name; + } + foreach ($prefixes as $prefix) { + if (function_exists($prefix . '_' . $template_phase)) { + $info[$phase_key][] = $prefix . '_' . $template_phase; + } + if (function_exists($prefix . '_' . $template_phase . '_' . $hook)) { + $info[$phase_key][] = $prefix . '_' . $template_phase . '_' . $hook; + } + } + } + // Check for the override flag and prevent the cached preprocess functions from being used. + // This allows themes or theme engines to remove preprocessors set earlier in the registry build. + if (!empty($info['override ' . $phase_key])) { + // Flag not needed inside the registry. + unset($result[$hook]['override ' . $phase_key]); } - if (function_exists($prefix . '_preprocess_' . $hook)) { - $info['preprocess functions'][] = $prefix . '_preprocess_' . $hook; + elseif (isset($cache[$hook][$phase_key]) && is_array($cache[$hook][$phase_key])) { + $info[$phase_key] = array_merge($cache[$hook][$phase_key], $info[$phase_key]); } + $result[$hook][$phase_key] = $info[$phase_key]; } } - // Check for the override flag and prevent the cached preprocess functions from being used. - // This allows themes or theme engines to remove preprocessors set earlier in the registry build. - if (!empty($info['override preprocess functions'])) { - // Flag not needed inside the registry. - unset($result[$hook]['override preprocess functions']); - } - elseif (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions'])) { - $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']); - } - $result[$hook]['preprocess functions'] = $info['preprocess functions']; } // Merge the newly created theme hooks into the existing cache. $cache = array_merge($cache, $result); } - // Let themes have preprocess functions even if they didn't register a template. + // Let themes have preprocess and process functions even if they didn't register a template. if ($type == 'theme' || $type == 'base_theme') { foreach ($cache as $hook => $info) { // Check only if it's a template and not registered by the theme or engine. @@ -377,14 +390,24 @@ function _theme_process_registry(&$cache if (!isset($info['preprocess functions'])) { $cache[$hook]['preprocess functions'] = array(); } + if (!isset($info['process functions'])) { + $cache[$hook]['process functions'] = array(); + } if (function_exists($name . '_preprocess')) { $cache[$hook]['preprocess functions'][] = $name . '_preprocess'; } + if (function_exists($name . '_process')) { + $cache[$hook]['process functions'][] = $name . '_process'; + } if (function_exists($name . '_preprocess_' . $hook)) { $cache[$hook]['preprocess functions'][] = $name . '_preprocess_' . $hook; } + if (function_exists($name . '_process_' . $hook)) { + $cache[$hook]['process functions'][] = $name . '_process_' . $hook; + } // Ensure uniqueness. $cache[$hook]['preprocess functions'] = array_unique($cache[$hook]['preprocess functions']); + $cache[$hook]['process functions'] = array_unique($cache[$hook]['process functions']); } } } @@ -661,13 +684,14 @@ function theme() { } } - if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) { - // This construct ensures that we can keep a reference through - // call_user_func_array. - $args = array(&$variables, $hook); - foreach ($info['preprocess functions'] as $preprocess_function) { - if (drupal_function_exists($preprocess_function)) { - call_user_func_array($preprocess_function, $args); + // This construct ensures that we can keep a reference through + // call_user_func_array. + $args = array(&$variables, $hook); + // Template functions in two phases. + foreach (array('preprocess functions', 'process functions') as $template_phase) { + foreach ($info[$template_phase] as $template_function) { + if (drupal_function_exists($template_function)) { + call_user_func_array($template_function, $args); } } } @@ -1782,6 +1806,9 @@ function template_preprocess(&$variables // Tell all templates where they are located. $variables['directory'] = path_to_theme(); + // Initialize html class attribute for the current hook. + $variables['classes_array'] = array($hook); + // Set default variables that depend on the database. $variables['is_admin'] = FALSE; $variables['is_front'] = FALSE; @@ -1801,6 +1828,14 @@ function template_preprocess(&$variables } /** + * A default process function used to alter variables as late as possible. + */ +function template_process(&$variables, $hook) { + // Flatten out classes. + $variables['classes'] = implode(' ', str_replace('_', '-', $variables['classes_array'])); +} + +/** * Process variables for page.tpl.php * * Most themes utilize their own copy of page.tpl.php. The default is located @@ -1896,11 +1931,10 @@ function template_preprocess_page(&$vari // Compile a list of classes that are going to be applied to the body element. // This allows advanced theming based on context (home page, node of certain type, etc.). - $body_classes = array(); // Add a class that tells us whether we're on the front page or not. - $body_classes[] = $variables['is_front'] ? 'front' : 'not-front'; + $variables['classes_array'][] = $variables['is_front'] ? 'front' : 'not-front'; // Add a class that tells us whether the page is viewed by an authenticated user or not. - $body_classes[] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in'; + $variables['classes_array'][] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in'; // Build a list of suggested template files and body classes in order of // specificity. One suggestion is made for every element of the current path, @@ -1926,7 +1960,7 @@ function template_preprocess_page(&$vari // more specific data like node-12 or node-edit. To avoid illegal characters in // the class, we're removing everything disallowed. We are not using 'a-z' as // that might leave in certain international characters (e.g. German umlauts). - $body_classes[] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', form_clean_id(drupal_strtolower($suggestion))); + $variables['classes_array'][] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', form_clean_id(drupal_strtolower($suggestion))); } } if (drupal_is_front_page()) { @@ -1938,20 +1972,18 @@ function template_preprocess_page(&$vari // If on an individual node page, add the node type to body classes. if (isset($variables['node']) && $variables['node']->type) { - $body_classes[] = 'node-type-' . form_clean_id($variables['node']->type); + $variables['classes_array'][] = 'node-type-' . form_clean_id($variables['node']->type); } // Add information about the number of sidebars. if ($variables['layout'] == 'both') { - $body_classes[] = 'two-sidebars'; + $variables['classes_array'][] = 'two-sidebars'; } elseif ($variables['layout'] == 'none') { - $body_classes[] = 'no-sidebars'; + $variables['classes_array'][] = 'no-sidebars'; } else { - $body_classes[] = 'one-sidebar sidebar-' . $variables['layout']; + $variables['classes_array'][] = 'one-sidebar sidebar-' . $variables['layout']; } - // Implode with spaces. - $variables['body_classes'] = implode(' ', $body_classes); } /** @@ -1997,6 +2029,24 @@ function template_preprocess_node(&$vari // Flatten the node object's member fields. $variables = array_merge((array)$node, $variables); + + // Gather node classes. + $variables['classes_array'][] = 'node-' . $node->type; + if ($variables['promote']) { + $variables['classes_array'][] = 'node-promoted'; + } + if ($variables['sticky']) { + $variables['classes_array'][] = 'node-sticky'; + } + if (!$variables['status']) { + $variables['classes_array'][] = 'node-unpublished'; + } + if ($variables['teaser']) { + $variables['classes_array'][] = 'node-teaser'; + } + if (isset($variables['preview'])) { + $variables['classes_array'][] = 'node-preview'; + } // Display post information only on certain node types. if (variable_get('node_submitted_' . $node->type, TRUE)) { @@ -2044,6 +2094,8 @@ function template_preprocess_block(&$var $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even'; $variables['block_id'] = $block_counter[$variables['block']->region]++; + $variables['classes_array'][] = 'block-' . $variables['block']->module; + $variables['template_files'][] = 'block-' . $variables['block']->region; $variables['template_files'][] = 'block-' . $variables['block']->module; $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta; Index: includes/theme.maintenance.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v retrieving revision 1.21 diff -u -p -r1.21 theme.maintenance.inc --- includes/theme.maintenance.inc 24 Nov 2008 10:41:39 -0000 1.21 +++ includes/theme.maintenance.inc 6 Apr 2009 09:32:04 -0000 @@ -266,21 +266,19 @@ function template_preprocess_maintenance $variables['closure'] = ''; // Compile a list of classes that are going to be applied to the body element. - $body_classes = array(); - $body_classes[] = 'in-maintenance'; + $variables['classes_array'][] = 'in-maintenance'; if (isset($variables['db_is_active']) && !$variables['db_is_active']) { - $body_classes[] = 'db-offline'; + $variables['classes_array'][] = 'db-offline'; } if ($variables['layout'] == 'both') { - $body_classes[] = 'two-sidebars'; + $variables['classes_array'][] = 'two-sidebars'; } elseif ($variables['layout'] == 'none') { - $body_classes[] = 'no-sidebars'; + $variables['classes_array'][] = 'no-sidebars'; } else { - $body_classes[] = 'one-sidebar sidebar-' . $variables['layout']; + $variables['classes_array'][] = 'one-sidebar sidebar-' . $variables['layout']; } - $variables['body_classes'] = implode(' ', $body_classes); // Dead databases will show error messages so supplying this template will // allow themers to override the page and the content completely. Index: modules/comment/comment-folded.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment-folded.tpl.php,v retrieving revision 1.4 diff -u -p -r1.4 comment-folded.tpl.php --- modules/comment/comment-folded.tpl.php 14 May 2008 13:12:40 -0000 1.4 +++ modules/comment/comment-folded.tpl.php 6 Apr 2009 09:32:04 -0000 @@ -11,11 +11,29 @@ * - $author: Comment author. Can be link or plain text. * - $date: Date and time of posting. * - $comment: Full comment object. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the following: + * - comment-folded: The current template type, i.e., "theming hook". + * - comment-by-anonymous: Comment by an unregistered user. + * - comment-by-node-author: Comment by the author of the parent node. + * The following applies only to viewers who are registered users: + * - comment-unpublished: An unpublished comment visible only to administrators. + * - comment-by-viewer: Comment by the user currently viewing the page. + * - comment-new: New comment since last the visit. + * + * These two variables are provided for context: + * - $comment: Full comment object. + * - $node: Node object the comments are attached to. + * + * Other variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. * * @see template_preprocess_comment_folded() * @see theme_comment_folded() */ ?> -
subject ?>
Index: modules/system/box.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/box.tpl.php,v retrieving revision 1.4 diff -u -p -r1.4 box.tpl.php --- modules/system/box.tpl.php 13 Oct 2008 12:31:43 -0000 1.4 +++ modules/system/box.tpl.php 6 Apr 2009 09:32:05 -0000 @@ -8,11 +8,19 @@ * Available variables: * - $title: Box title. * - $content: Box content. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default value has the following: + * - box: The current template type, i.e., "theming hook". + * + * Other variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. * * @see template_preprocess() */ ?> -subject ?>
Index: themes/garland/comment.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/comment.tpl.php,v retrieving revision 1.12 diff -u -p -r1.12 comment.tpl.php --- themes/garland/comment.tpl.php 18 Feb 2009 14:28:25 -0000 1.12 +++ themes/garland/comment.tpl.php 6 Apr 2009 09:32:05 -0000 @@ -1,7 +1,7 @@ -