Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1024
diff -u -p -r1.1024 common.inc
--- includes/common.inc	17 Oct 2009 05:50:27 -0000	1.1024
+++ includes/common.inc	18 Oct 2009 00:06:48 -0000
@@ -5101,6 +5101,9 @@ function drupal_common_theme() {
     'indentation' => array(
       'arguments' => array('size' => 1),
     ),
+    'template_variable_wrapper' => array(
+      'arguments' => array('content' => NULL, 'attributes' => array(), 'context' => array(), 'inline' => TRUE),
+    ),
     // from theme.maintenance.inc
     'maintenance_page' => array(
       'arguments' => array('content' => NULL, 'show_messages' => TRUE),
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.537
diff -u -p -r1.537 theme.inc
--- includes/theme.inc	16 Oct 2009 08:27:40 -0000	1.537
+++ includes/theme.inc	18 Oct 2009 00:06:48 -0000
@@ -2030,6 +2030,71 @@ function theme_indentation($variables) {
 }
 
 /**
+ * Wrap a template variable in an HTML element with the desired attributes.
+ *
+ * This is called by template_process() shortly before the theme system renders
+ * a template file. It is called once for each template variable for which
+ * modules have registered additional attributes that are needed around the
+ * variable. While template files are responsible for rendering the attributes
+ * for the template's primary object (via the $attributes variable) and primary
+ * title (via the $title_attributes variable), additional template variables
+ * that need containing attributes are routed through this function, allowing
+ * the template file to already receive properly wrapped variables.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - content: A string of content to be wrapped. The wrapped version of this
+ *     content will be sent to the template for which this function is called
+ *     as one of its variables.
+ *   - attributes: An array of attributes desired on the wrapping element (can
+ *     be passed to drupal_attributes()).
+ *   - context: An array of context information about the content to be wrapped:
+ *     - 'hook': The theme hook that will use the wrapped content. This
+ *       corresponds to the key within the theme registry for this template.
+ *       For example, if this content is about to be used in node.tpl.php or
+ *       node-TYPE.tpl.php, then the 'hook' is 'node'.
+ *     - 'variable_name': The name of the variable, by which the template will
+ *       refer to this content. Each template file has documentation about
+ *       the variables it uses. For example, if this function is called in
+ *       preparing the $author variable for comment.tpl.php, then the
+ *       'variable_name' is 'author'.
+ *     - 'variables': The full array of variables about to be passed to the
+ *       template.
+ *   - inline: TRUE if the content contains only inline HTML elements and
+ *     therefore can be validly wrapped by a 'span' tag. FALSE if the content
+ *     might contain block level HTML elements and therefore cannot be validly
+ *     wrapped by a 'span' tag. Modules implementing preprocess functions that
+ *     set 'variable_attributes_array' for a particular template variable that
+ *     might contain block level HTML must also implement
+ *     hook_preprocess_template_variable_wrapper() and set 'inline' to FALSE
+ *     for that context. Themes that render normally inline content with block
+ *     level HTML must similarly implement
+ *     hook_preprocess_template_variable_wrapper() and set 'inline' accordingly.
+ *
+ * @return
+ *   A string containing the wrapped content.
+ *
+ * @see template_process()
+ *
+ * Tip for themers: if you're already outputting a wrapper element around a
+ * particular template variable in your template file and if you don't want
+ * an extra wrapper element, you can override this function to not wrap that
+ * variable and instead print:
+ * @code
+ * drupal_attributes($variable_attributes_array[$variable_name])
+ * @endcode
+ * inside your template file.
+ */
+function theme_template_variable_wrapper($variables) {
+  $output = $variables['content'];
+  if (!empty($output) && !empty($variables['attributes'])) {
+    $attributes = drupal_attributes($variables['attributes']);
+    $output = $variables['inline'] ? "<span$attributes>$output</span>" : "<div$attributes>$output</div>";
+  }
+  return $output;
+}
+
+/**
  * @} End of "defgroup themeable".
  */
 
@@ -2110,6 +2175,15 @@ function template_process(&$variables, $
   // Flatten out attributes and title_attributes.
   $variables['attributes'] = drupal_attributes($variables['attributes_array']);
   $variables['title_attributes'] = drupal_attributes($variables['title_attributes_array']);
+
+  // Modules may use variable_attributes_array to register attributes (and
+  // therefore an element) needed around a particular template variable.
+  if (!empty($variables['variable_attributes_array'])) {
+    foreach ($variables['variable_attributes_array'] as $variable_name => $attributes) {
+      $context = array('hook' => $hook, 'variable_name' => $variable_name, 'variables' => $variables);
+      $variables[$variable_name] = theme('template_variable_wrapper', array('content' => $variables[$variable_name], 'attributes' => $attributes, 'context' => $context));
+    }
+  }
 }
 
 /**
