Commit dc5e3349 authored by alexpott's avatar alexpott

Issue #2042285 by thedavidmeister, jenlampton, Mark Carver: #theme_wrappers()...

Issue #2042285 by thedavidmeister, jenlampton, Mark Carver: #theme_wrappers() should be able to have a unique set of variables per wrapper hook.
parent faaaaae6
......@@ -3730,7 +3730,31 @@ function drupal_render_page($page) {
* - If this element has an array of #theme_wrappers defined and
* #render_children is not set, #children is then re-rendered by passing the
* element in its current state to theme() successively for each item in
* #theme_wrappers.
* #theme_wrappers. Since #theme and #theme_wrappers hooks often define
* variables with the same names it is possible to explicitly override each
* attribute passed to each #theme_wrappers hook by setting the hook name as
* the key and an array of overrides as the value in #theme_wrappers array.
* For example, if we have a render element as follows:
* @code
* array(
* '#theme' => 'image',
* '#attributes' => array('class' => 'foo'),
* '#theme_wrappers' => array('container'),
* );
* @endcode
* and we need to pass the class 'bar' as an attribute for 'container', we
* can rewrite our element thus:
* @code
* array(
* '#theme' => 'image',
* '#attributes' => array('class' => 'foo'),
* '#theme_wrappers' => array(
* 'container' => array(
* '#attributes' => array('class' => 'bar'),
* ),
* ),
* );
* @endcode
* - If this element has an array of #post_render functions defined, they are
* called sequentially to modify the rendered #children. Unlike #pre_render
* functions, #post_render functions are passed both the rendered #children
......@@ -3859,8 +3883,24 @@ function drupal_render(&$elements) {
// If the internal #render_children property is set, do not call the
// #theme_wrappers function(s) to prevent infinite recursion.
if (isset($elements['#theme_wrappers']) && !isset($elements['#render_children'])) {
foreach ($elements['#theme_wrappers'] as $theme_wrapper) {
$elements['#children'] = theme($theme_wrapper, $elements);
foreach ($elements['#theme_wrappers'] as $key => $value) {
// If the value of a #theme_wrappers item is an array then the theme hook
// is found in the key of the item and the value contains attribute
// overrides. Attribute overrides replace key/value pairs in $elements for
// only this theme() call. This allows #theme hooks and #theme_wrappers
// hooks to share variable names without conflict or ambiguity.
$wrapper_elements = $elements;
if (is_array($value)) {
$wrapper_hook = $key;
foreach ($value as $attribute => $override) {
$wrapper_elements[$attribute] = $override;
}
}
else {
$wrapper_hook = $value;
}
$elements['#children'] = theme($wrapper_hook, $wrapper_elements);
}
}
......
......@@ -73,6 +73,68 @@ function testDrupalRenderBasics() {
'expected' => '',
),
// Test that #theme and #theme_wrappers can co-exist on an element.
array(
'name' => '#theme and #theme_wrappers basic',
'value' => array(
'#theme' => 'common_test_foo',
'#foo' => 'foo',
'#bar' => 'bar',
'#theme_wrappers' => array('container'),
'#attributes' => array('class' => 'baz'),
),
'expected' => '<div class="baz">foobar</div>',
),
// Test that #theme_wrappers can disambiguate element attributes shared
// with rendering methods that build #children by using the alternate
// #theme_wrappers attribute override syntax.
array(
'name' => '#theme and #theme_wrappers attribute disambiguation',
'value' => array(
'#type' => 'link',
'#theme_wrappers' => array(
'container' => array(
'#attributes' => array('class' => 'baz'),
),
),
'#attributes' => array('id' => 'foo'),
'#href' => 'http://drupal.org',
'#title' => 'bar',
),
'expected' => '<div class="baz"><a href="http://drupal.org" id="foo">bar</a></div>',
),
// Test that #theme_wrappers can disambiguate element attributes when the
// "base" attribute is not set for #theme.
array(
'name' => '#theme_wrappers attribute disambiguation with undefined #theme attribute',
'value' => array(
'#type' => 'link',
'#href' => 'http://drupal.org',
'#title' => 'foo',
'#theme_wrappers' => array(
'container' => array(
'#attributes' => array('class' => 'baz'),
),
),
),
'expected' => '<div class="baz"><a href="http://drupal.org">foo</a></div>',
),
// Two 'container' #theme_wrappers, one using the "base" attributes and
// one using an override.
array(
'name' => 'Two #theme_wrappers container hooks with different attributes',
'value' => array(
'#attributes' => array('class' => 'foo'),
'#theme_wrappers' => array(
'container' => array(
'#attributes' => array('class' => 'bar'),
),
'container',
),
),
'expected' => '<div class="foo"><div class="bar"></div></div>',
),
// Test handling of #markup as a fallback for #theme hooks.
// Simple #markup with no theme.
array(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment