Commit 4b247824 authored by catch's avatar catch

Issue #256827 by sun, zeta ζ: Fixed Various bugs in theme_item_list().

parent 17329b16
......@@ -6459,7 +6459,7 @@ function drupal_common_theme() {
'variables' => array('type' => MARK_NEW),
),
'item_list' => array(
'variables' => array('items' => array(), 'title' => NULL, 'type' => 'ul', 'attributes' => array()),
'variables' => array('items' => array(), 'title' => '', 'type' => 'ul', 'attributes' => array()),
),
'more_help_link' => array(
'variables' => array('url' => NULL),
......
......@@ -1793,12 +1793,14 @@ function theme_mark($variables) {
*
* @param $variables
* An associative array containing:
* - items: An array of items to be displayed in the list. If an item is a
* string, then it is used as is. If an item is an array, then the "data"
* element of the array is used as the contents of the list item. If an item
* is an array with a "children" element, those children are displayed in a
* nested list. All other elements are treated as attributes of the list
* item element.
* - items: A list of items to render. String values are rendered as is. Each
* item can also be an associative array containing:
* - data: The string content of the list item.
* - children: A list of nested child items to render that behave
* identically to 'items', but any non-numeric string keys are treated as
* HTML attributes for the child list that wraps 'children'.
* Any other key/value pairs are used as HTML attributes for the list item
* in 'data'.
* - title: The title of the list.
* - type: The type of list to return (e.g. "ul", "ol").
* - attributes: The attributes applied to the list element.
......@@ -1807,51 +1809,69 @@ function theme_item_list($variables) {
$items = $variables['items'];
$title = $variables['title'];
$type = $variables['type'];
$attributes = $variables['attributes'];
$list_attributes = $variables['attributes'];
$output = '<div class="item-list">';
if (isset($title)) {
$output .= '<h3>' . $title . '</h3>';
}
$output = '';
if ($items) {
$output .= '<' . $type . drupal_attributes($list_attributes) . '>';
if (!empty($items)) {
$output .= "<$type" . drupal_attributes($attributes) . '>';
$num_items = count($items);
foreach ($items as $i => $item) {
$i = 0;
foreach ($items as $key => $item) {
$i++;
$attributes = array();
$children = array();
$data = '';
if (is_array($item)) {
foreach ($item as $key => $value) {
if ($key == 'data') {
$data = $value;
}
elseif ($key == 'children') {
$children = $value;
}
else {
$attributes[$key] = $value;
$value = '';
if (isset($item['data'])) {
$value .= $item['data'];
}
$attributes = array_diff_key($item, array('data' => 0, 'children' => 0));
// Append nested child list, if any.
if (isset($item['children'])) {
// HTML attributes for the outer list are defined in the 'attributes'
// theme variable, but not inherited by children. For nested lists,
// all non-numeric keys in 'children' are used as list attributes.
$child_list_attributes = array();
foreach ($item['children'] as $child_key => $child_item) {
if (is_string($child_key)) {
$child_list_attributes[$child_key] = $child_item;
unset($item['children'][$child_key]);
}
}
$value .= theme('item_list', array(
'items' => $item['children'],
'type' => $type,
'attributes' => $child_list_attributes,
));
}
}
else {
$data = $item;
}
if (count($children) > 0) {
// Render nested list.
$data .= theme_item_list(array('items' => $children, 'title' => NULL, 'type' => $type, 'attributes' => $attributes));
$value = $item;
}
if ($i == 0) {
$attributes['class'][] = ($i % 2 ? 'odd' : 'even');
if ($i == 1) {
$attributes['class'][] = 'first';
}
if ($i == $num_items - 1) {
if ($i == $num_items) {
$attributes['class'][] = 'last';
}
$output .= '<li' . drupal_attributes($attributes) . '>' . $data . "</li>\n";
$output .= '<li' . drupal_attributes($attributes) . '>' . $value . '</li>';
}
$output .= "</$type>";
}
$output .= '</div>';
// Only output the list container and title, if there are any list items.
if ($output !== '') {
if ($title !== '') {
$title = '<h3>' . $title . '</h3>';
}
$output = '<div class="item-list">' . $title . $output . '</div>';
}
return $output;
}
......
......@@ -164,30 +164,101 @@ class ThemeTableUnitTest extends DrupalWebTestCase {
}
/**
* Unit tests for theme_item_list().
* Tests for common theme functions.
*/
class ThemeItemListUnitTest extends DrupalWebTestCase {
class ThemeFunctionsTestCase extends DrupalWebTestCase {
protected $profile = 'testing';
public static function getInfo() {
return array(
'name' => 'Theme item list',
'description' => 'Test the theme_item_list() function.',
'name' => 'Theme functions',
'description' => 'Tests common theme functions.',
'group' => 'Theme',
);
}
/**
* Test nested list rendering.
* Tests theme_item_list().
*/
function testNestedList() {
$items = array('a', array('data' => 'b', 'children' => array('c', 'd')), 'e');
$expected = '<div class="item-list"><ul><li class="first">a</li>
<li>b<div class="item-list"><ul><li class="first">c</li>
<li class="last">d</li>
</ul></div></li>
<li class="last">e</li>
</ul></div>';
$output = theme('item_list', array('items' => $items));
$this->assertIdentical($expected, $output, 'Nested list is rendered correctly.');
function testItemList() {
// Verify that empty variables produce no output.
$variables = array();
$expected = '';
$this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback generates no output.');
$variables = array();
$variables['title'] = 'Some title';
$expected = '';
$this->assertThemeOutput('item_list', $variables, $expected, 'Empty %callback with title generates no output.');
// Verify nested item lists.
$variables = array();
$variables['title'] = 'Some title';
$variables['attributes'] = array(
'id' => 'parentlist',
);
$variables['items'] = array(
'a',
array(
'data' => 'b',
'children' => array(
'c',
// Nested children may use additional attributes.
array(
'data' => 'd',
'class' => array('dee'),
),
// Any string key is treated as child list attribute.
'id' => 'childlist',
),
// Any other keys are treated as item attributes.
'id' => 'bee',
),
array(
'data' => 'e',
'id' => 'E',
),
);
$inner = '<div class="item-list"><ul id="childlist">';
$inner .= '<li class="odd first">c</li>';
$inner .= '<li class="dee even last">d</li>';
$inner .= '</ul></div>';
$expected = '<div class="item-list">';
$expected .= '<h3>Some title</h3>';
$expected .= '<ul id="parentlist">';
$expected .= '<li class="odd first">a</li>';
$expected .= '<li id="bee" class="even">b' . $inner . '</li>';
$expected .= '<li id="E" class="odd last">e</li>';
$expected .= '</ul></div>';
$this->assertThemeOutput('item_list', $variables, $expected);
}
/**
* Asserts themed output.
*
* @param $callback
* The name of the theme function to invoke; e.g. 'links' for theme_links().
* @param $variables
* An array of variables to pass to the theme function.
* @param $expected
* The expected themed output string.
* @param $message
* (optional) An assertion message.
*/
protected function assertThemeOutput($callback, array $variables = array(), $expected, $message = '') {
$output = theme($callback, $variables);
$this->verbose('Variables:' . '<pre>' . check_plain(var_export($variables, TRUE)) . '</pre>'
. '<hr />' . 'Result:' . '<pre>' . check_plain(var_export($output, TRUE)) . '</pre>'
. '<hr />' . 'Expected:' . '<pre>' . check_plain(var_export($expected, TRUE)) . '</pre>'
. '<hr />' . $output
);
if (!$message) {
$message = '%callback rendered correctly.';
}
$message = t($message, array('%callback' => 'theme_' . $callback . '()'));
$this->assertIdentical($output, $expected, $message);
}
}
......
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