diff --git a/includes/common.inc b/includes/common.inc index 44ff460787..ad8516f2fb 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -6952,7 +6952,16 @@ 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 a926b764ed..c9d80584b5 100644 --- a/includes/theme.inc +++ b/includes/theme.inc @@ -1911,7 +1911,7 @@ function theme_breadcrumb($variables) { /** * Returns HTML for a table. * - * @param $variables + * @param array $variables * An associative array containing: * - header: An array containing the table headers. Each element of the array * can be either a localized string or an associative array with the @@ -1948,6 +1948,8 @@ function theme_breadcrumb($variables) { * ) * ); * @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 @@ -1984,8 +1986,11 @@ function theme_breadcrumb($variables) { * - sticky: Use a "sticky" table header. * - empty: The message to display in an extra row if table does not have any * rows. + * + * @return string + * The HTML output. */ -function theme_table($variables) { +function theme_table(array $variables) { $header = $variables['header']; $rows = $variables['rows']; $attributes = $variables['attributes']; @@ -2049,17 +2054,31 @@ function theme_table($variables) { if (!empty($header)) { foreach ($header as $header_cell) { if (is_array($header_cell)) { - $header_count += isset($header_cell['colspan']) ? $header_cell['colspan'] : 1; + $header_count += isset($header_cell['colspan']) ? + $header_cell['colspan'] : 1; } else { $header_count++; } } } - $rows[] = array(array('data' => $empty, 'colspan' => $header_count, 'class' => array('empty', 'message'))); + $rows[] = array( + array( + 'data' => $empty, + 'colspan' => $header_count, + 'class' => array( + 'empty', + 'message' + ), + ), + ); } - // Format the table header: + // Assigning back the $rows variable into $variables as we won't modify it + // anymore. + $variables['rows'] = $rows; + + // Format the table header. if (!empty($header)) { $ts = tablesort_init($header); // HTML requires that the thead tag has tr tags in it followed by tbody @@ -2069,23 +2088,38 @@ function theme_table($variables) { $cell = tablesort_header($cell, $header, $ts); $output .= _theme_table_cell($cell, TRUE); } - // Using ternary operator to close the tags based on whether or not there are rows + // Using ternary operator to close the tags based on whether + // or not there are rows. $output .= (!empty($rows) ? " \n" : "\n"); } else { $ts = array(); } - // Format the table rows: + $sections = array(); + if (!empty($rows)) { - $output .= "\n"; + $sections['tbody'] = $rows; + } + + if (!empty($variables['footer'])) { + $sections['tfoot'] = $variables['footer']; + } + + // tbody and tfoot have the same structure and are built using the same + // procedure. + foreach ($sections as $tag => $content) { + $output .= "<" . $tag . ">\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 + $no_striping = $tag === 'tfoot'; + + foreach ($content 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; + $no_striping = isset($row['no_striping']) ? + $row['no_striping'] : $no_striping; // Set the attributes array and exclude 'data' and 'no_striping'. $attributes = $row; @@ -2097,14 +2131,15 @@ function theme_table($variables) { $attributes = array(); $no_striping = FALSE; } + if (!empty($cells)) { - // Add odd/even class + // Add odd/even class. if (!$no_striping) { $class = $flip[$class]; $attributes['class'][] = $class; } - // Build row + // Build row. $output .= ' '; $i = 0; foreach ($cells as $cell) { @@ -2114,10 +2149,12 @@ function theme_table($variables) { $output .= " \n"; } } - $output .= "\n"; + + $output .= "\n"; } $output .= "\n"; + return $output; } diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test index 5f095bd558..710a56e5ef 100644 --- a/modules/simpletest/tests/theme.test +++ b/modules/simpletest/tests/theme.test @@ -238,6 +238,27 @@ class ThemeTableTestCase extends DrupalWebTestCase { $this->assertNoRaw('class="odd"', 'Odd/even classes were not added because $no_striping = TRUE.'); $this->assertNoRaw('no_striping', 'No invalid no_striping HTML attribute was printed.'); } + + /** + * 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('1Foo', 'Table footer found.'); + } } /**