diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc index cd5c0c1..5a0f4dc 100644 --- a/core/includes/tablesort.inc +++ b/core/includes/tablesort.inc @@ -38,19 +38,19 @@ function tablesort_init($header) { * The current table sort context as returned from tablesort_init(). * * @return - * A properly formatted cell, ready for _theme_table_cell(). + * A properly formatted cell. */ function tablesort_header($cell, $header, $ts) { // Special formatting for the currently sorted column header. - if (is_array($cell) && isset($cell['field'])) { + if (isset($cell['field'])) { $title = t('sort by @s', array('@s' => $cell['data'])); if ($cell['data'] == $ts['name']) { // aria-sort is a WAI-ARIA property that indicates if items in a table // or grid are sorted in ascending or descending order. See // http://www.w3.org/TR/wai-aria/states_and_properties#aria-sort - $cell['aria-sort'] = ($ts['sort'] == 'asc') ? 'ascending' : 'descending'; + $cell['attributes']['aria-sort'] = ($ts['sort'] == 'asc') ? 'ascending' : 'descending'; $ts['sort'] = (($ts['sort'] == 'asc') ? 'desc' : 'asc'); - $cell['class'][] = 'active'; + $cell['attributes']['class'][] = 'active'; $tablesort_indicator = array( '#theme' => 'tablesort_indicator', '#style' => $ts['sort'], @@ -70,35 +70,6 @@ function tablesort_header($cell, $header, $ts) { } /** - * Formats a table cell. - * - * Adds a class attribute to all cells in the currently active column. - * - * @param $cell - * The cell to format. - * @param $header - * An array of column headers in the format described in '#type' => 'table'. - * @param $ts - * The current table sort context as returned from tablesort_init(). - * @param $i - * The index of the cell's table column. - * - * @return - * A properly formatted cell, ready for _theme_table_cell(). - */ -function tablesort_cell($cell, $header, $ts, $i) { - if (isset($header[$i]['data']) && $header[$i]['data'] == $ts['name'] && !empty($header[$i]['field'])) { - if (is_array($cell)) { - $cell['class'][] = 'active'; - } - else { - $cell = array('data' => $cell, 'class' => array('active')); - } - } - return $cell; -} - -/** * Composes a URL query parameter array for table sorting links. * * @return diff --git a/core/includes/theme.inc b/core/includes/theme.inc index f98df80..eaf26ad 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1537,9 +1537,18 @@ function theme_table($variables) { // HTML requires that the thead tag has tr tags in it followed by tbody // tags. Using ternary operator to check and see if we have any rows. $output .= (count($rows) ? ' ' : ' '); - $i = 0; - foreach ($header as $cell) { - $i++; + foreach ($header as $i => $cell) { + // If the cell is not an array, make it one. + if (!is_array($cell)) { + $cell = array('data' => $cell); + } + $cell['data'] = isset($cell['data']) ? $cell['data'] : ''; + $cell['attributes'] = isset($cell['attributes']) ? $cell['data'] : array(); + + // Flag the cell as a header or not and remove the flag. + $is_header = isset($cell['header']) ? $cell['header'] : TRUE; + unset($cell['header']); + // Track responsive classes for each column as needed. Only the header // cells for a column are marked up with the responsive classes by a // module developer or themer. The responsive classes on the header cells @@ -1553,7 +1562,20 @@ function theme_table($variables) { } } $cell = tablesort_header($cell, $header, $ts); - $output .= _theme_table_cell($cell, TRUE); + + // Move cell properties that are not data or attributes into attributes. + // Doing this after tablesort_header because it removes the sort and field + // keys. + foreach ($cell as $key => $value) { + if ($key != 'data' && $key != 'attributes') { + $cell['attributes'][$key] = $value; + } + } + if (is_array($cell['data'])) { + $cell['data'] = drupal_render($cell['data']); + } + $cell_tag = ($is_header) ? 'th' : 'td'; + $output .= '<' . $cell_tag . new Attribute($cell['attributes']) . '>' . $cell['data'] . ''; } // Using ternary operator to close the tags based on whether or not there are rows $output .= (count($rows) ? " \n" : "\n"); @@ -1595,19 +1617,39 @@ function theme_table($variables) { $i = 0; foreach ($cells as $cell) { $i++; + // If the cell is not an array, make it one. + if (!is_array($cell)) { + $cell = array('data' => $cell); + } + $cell['data'] = isset($cell['data']) ? $cell['data'] : ''; + $cell['attributes'] = isset($cell['attributes']) ? $cell['data'] : array(); + + // Flag the cell as a header or not and remove the flag. + $is_header = !empty($cell['header']); + unset($cell['header']); + + // Move cell properties that are not data or attributes + // into attributes. + foreach ($cell as $key => $value) { + if ($key != 'data' && $key != 'attributes') { + $cell['attributes'][$key] = $value; + } + } + // Add active class if needed for sortable tables. - $cell = tablesort_cell($cell, $header, $ts, $i); + if (isset($header[$i]['data']) && $header[$i]['data'] == $ts['name'] && !empty($header[$i]['field'])) { + $cell['attributes']['class'][] = 'active'; + } // Copy RESPONSIVE_PRIORITY_LOW/RESPONSIVE_PRIORITY_MEDIUM // class from header to cell as needed. if (isset($responsive[$i])) { - if (is_array($cell)) { - $cell['class'][] = $responsive[$i]; - } - else { - $cell = array('data' => $cell, 'class' => $responsive[$i]); - } + $cell['attributes']['class'][] = $responsive[$i]; + } + if (is_array($cell['data'])) { + $cell['data'] = drupal_render($cell['data']); } - $output .= _theme_table_cell($cell); + $cell_tag = ($is_header) ? 'th' : 'td'; + $output .= '<' . $cell_tag . new Attribute($cell['attributes']) . '>' . $cell['data'] . ''; } $output .= " \n"; } @@ -1792,47 +1834,6 @@ function template_preprocess_container(&$variables) { */ /** - * Returns HTML output for a single table cell for theme_table(). - * - * @param $cell - * Array of cell information, or string to display in cell. - * @param bool $header - * TRUE if this cell is a table header cell, FALSE if it is an ordinary - * table cell. If $cell is an array with element 'header' set to TRUE, that - * will override the $header parameter. - * - * @return - * HTML for the cell. - */ -function _theme_table_cell($cell, $header = FALSE) { - $attributes = ''; - - if (is_array($cell)) { - $data = isset($cell['data']) ? $cell['data'] : ''; - // Cell's data property can be a string or a renderable array. - if (is_array($data)) { - $data = drupal_render($data); - } - $header |= isset($cell['header']); - unset($cell['data']); - unset($cell['header']); - $attributes = new Attribute($cell); - } - else { - $data = $cell; - } - - if ($header) { - $output = "$data"; - } - else { - $output = "$data"; - } - - return $output; -} - -/** * Adds a default set of helper variables for preprocessors and templates. * * This function is called for theme hooks implemented as templates only, not diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php index a5502e7..2376399 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TableTest.php @@ -106,4 +106,24 @@ function testThemeTableWithNoStriping() { $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.'); } + + /** + * Tests that the 'header' option in cells works correctly. + */ + function testThemeTableHeaderCellOption() { + $rows = array( + array( + array('data' => 1, 'header' => TRUE), + array('data' => 1, 'header' => FALSE), + array('data' => 1), + ), + ); + $table = array( + '#type' => 'table', + '#rows' => $rows, + ); + $this->content = drupal_render($table); + $this->assertRaw('111', 'The th and td tags was printed correctly.'); + } + }