diff --git a/includes/common.inc b/includes/common.inc
index da8996a1b9..6bf9e05697 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -6934,7 +6934,7 @@ function drupal_common_theme() {
'variables' => array(),
),
'table' => array(
- 'variables' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => TRUE, 'empty' => ''),
+ 'variables' => array('header' => NULL, 'footer' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'colgroups' => array(), 'sticky' => TRUE, 'empty' => ''),
),
'tablesort_indicator' => array(
'variables' => array('style' => NULL),
diff --git a/includes/theme.inc b/includes/theme.inc
index 9b606e9fb1..cea717765a 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -1916,24 +1916,24 @@ function theme_breadcrumb($variables) {
* - header: An array containing the table headers. Each element of the array
* can be either a localized string or an associative array with the
* following keys:
- * - "data": The localized title of the table column.
- * - "field": The database field represented in the table column (required
- * if user is to be able to sort on this column).
- * - "sort": A default sort order for this column ("asc" or "desc"). Only
- * one column should be given a default sort order because table sorting
+ * - data: The localized title of the table column.
+ * - field: The database field represented in the table column (required if
+ * user is to be able to sort on this column).
+ * - sort: A default sort order for this column ("asc" or "desc"). Only one
+ * column should be given a default sort order because table sorting
* only applies to one column at a time.
* - Any HTML attributes, such as "colspan", to apply to the column header
* cell.
* - rows: An array of table rows. Every row is an array of cells, or an
* associative array with the following keys:
- * - "data": an array of cells
+ * - data: an array of cells
* - Any HTML attributes, such as "class", to apply to the table row.
- * - "no_striping": a boolean indicating that the row should receive no
+ * - no_striping: a boolean indicating that the row should receive no
* 'even / odd' styling. Defaults to FALSE.
* Each cell can be either a string or an associative array with the
* following keys:
- * - "data": The string to display in the table cell.
- * - "header": Indicates this cell is a header.
+ * - data: The string to display in the table cell.
+ * - header: Indicates this cell is a header.
* - Any HTML attributes, such as "colspan", to apply to the table cell.
* Here's an example for $rows:
* @code
@@ -1945,9 +1945,11 @@ function theme_breadcrumb($variables) {
* // Row with attributes on the row and some of its cells.
* array(
* 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => array('funky')
- * )
+ * ),
* );
* @endcode
+ * - footer: An array of table rows which will be printed within a
+ * tag, in the same format as the rows element (see above).
* - attributes: An array of HTML attributes to apply to the table tag.
* - caption: A localized string to use for the tag.
* - colgroups: An array of column groups. Each element of the array can be
@@ -2054,7 +2056,7 @@ function theme_table($variables) {
$header_count++;
}
}
- $rows[] = array(array('data' => $empty, 'colspan' => $header_count, 'class' => array('empty', 'message')));
+ $variables['rows'][] = array(array('data' => $empty, 'colspan' => $header_count, 'class' => array('empty', 'message')));
}
// Format the table header:
@@ -2074,45 +2076,51 @@ function theme_table($variables) {
$ts = array();
}
- // Format the table rows:
- if (count($rows)) {
- $output .= "\n";
- $flip = array('even' => 'odd', 'odd' => 'even');
- $class = 'even';
- foreach ($rows as $number => $row) {
- // Check if we're dealing with a simple or complex row
- if (isset($row['data'])) {
- $cells = $row['data'];
- $no_striping = isset($row['no_striping']) ? $row['no_striping'] : FALSE;
-
- // Set the attributes array and exclude 'data' and 'no_striping'.
- $attributes = $row;
- unset($attributes['data']);
- unset($attributes['no_striping']);
- }
- else {
+ // Rows and footer have the same structure.
+ $sections = array(
+ 'rows' => 'tbody',
+ 'footer' => 'tfoot',
+ );
+ foreach ($sections as $section => $tag) {
+ if (!empty($variables[$section])) {
+ $output .= "<" . $tag . ">\n";
+ $flip = array('even' => 'odd', 'odd' => 'even');
+ $class = 'even';
+ foreach ($variables[$section] as $number => $row) {
$cells = $row;
$attributes = array();
- $no_striping = FALSE;
- }
- if (count($cells)) {
- // Add odd/even class
+ $no_striping = $section === 'footer';
+
+ // Check if we're dealing with a simple or complex row.
+ if (isset($row['data'])) {
+ $cells = $row['data'];
+ $no_striping = isset($row['no_striping']) ? $row['no_striping'] : $no_striping;
+
+ // Set the attributes array and exclude 'data' and 'no_striping'.
+ $attributes = $row;
+ unset($attributes['data']);
+ unset($attributes['no_striping']);
+ }
+
+ // Add odd/even class.
if (!$no_striping) {
$class = $flip[$class];
$attributes['class'][] = $class;
}
- // Build row
- $output .= ' ';
- $i = 0;
- foreach ($cells as $cell) {
- $cell = tablesort_cell($cell, $header, $ts, $i++);
- $output .= _theme_table_cell($cell);
+ // Build row.
+ if (!empty($cells)) {
+ $output .= '
';
+ $i = 0;
+ foreach ($cells as $cell) {
+ $cell = tablesort_cell($cell, $header, $ts, $i++);
+ $output .= _theme_table_cell($cell);
+ }
+ $output .= "
\n";
}
- $output .= " \n";
}
+ $output .= "" . $tag . ">\n";
}
- $output .= "\n";
}
$output .= "\n";
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index 5f095bd558..f899aee4c2 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -179,6 +179,27 @@ class ThemeTableTestCase extends DrupalWebTestCase {
}
/**
+ * Test that the 'footer' option works correctly.
+ */
+ function testThemeTableFooter() {
+ $footer = array(
+ array(
+ 'data' => array(1),
+ ),
+ array('Foo'),
+ );
+
+ $table = array(
+ 'rows' => array(),
+ 'footer' => $footer,
+ );
+
+ $this->content = theme('table', $table);
+ $this->content = preg_replace('@>\s+<@', '><', $this->content);
+ $this->assertRaw('1 |
Foo |
', 'Table footer found.');
+ }
+
+ /**
* Tableheader.js provides 'sticky' table headers, and is included by default.
*/
function testThemeTableStickyHeaders() {