Skip to content

Commit

Permalink
Fix output issue with PHP >= 7.3.
Browse files Browse the repository at this point in the history
Improve code.
Improve comments.
  • Loading branch information
strarsis committed Jan 5, 2020
1 parent 9abde20 commit 80ef3ec
Showing 1 changed file with 69 additions and 61 deletions.
130 changes: 69 additions & 61 deletions tablepress-rowspan-all.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
Plugin Name: TablePress Extension: Rowspans everywhere
Description: Allows using rowspans in thead.
Version: 1.1.0
Version: 1.2.0
Author: strarsis <[email protected]>
GitHub Plugin URI: strarsis/tablepress-rowspan-all
*/
Expand All @@ -13,120 +13,128 @@
const TABLEPRESS_ROWSPAN_OUTSIDE = '#outside_rowspan#';


// change trigger words in table header to preserve them
// (TablePress already uses #rowspan# but only between body cells, not table head + body cells)
add_filter('tablepress_table_raw_render_data', function($table, $render_options)
{

// Replace #rowspan# trigger word in table header (thead) cells with something else to preserve them
// as they would be, although ignored by TablePress, they are still cleaned up by it
// @see https://github.com/TobiasBg/TablePress/blob/master/classes/class-render.php#L53
// (TablePress already uses #rowspan# but only between table body cells, it ignores it between table header and body cells)
function tablepress_ext_rowspan_all_trigger_words($table, $render_options) {
// $table is a nested array

// rows
$rows = $table['data'];

// more than two row for thead + potential rowspan making sense at all
if (count($rows) <= 1)
return $table; // skip

// with a tfoot, there must be at least three rows (header, middle, footer)
if ($render_options['table_head'] && (!$render_options['table_foot'] || $render_options['table_foot'] && count($rows) <= 2)) {

$last_row_no = 0;
for ($row_no = 1; $row_no < count($rows); $row_no++) {
$row = $rows[$row_no];

for ($col_no = 0; $col_no < count($row); $col_no++) {
$col = $row[$col_no];

// only continous rows after head
if ($col === TABLEPRESS_ROWSPAN) {
if ($row_no > ($last_row_no + 1))
return $table; // skip table

$last_row_no = $row_no;

$table['data'][$row_no][$col_no] = TABLEPRESS_ROWSPAN_OUTSIDE;
}

}

}

}

return $table;
}, 10, 2);
}
add_filter('tablepress_table_raw_render_data', 'tablepress_ext_rowspan_all_trigger_words', 10, 2);

add_filter('tablepress_table_output', function($output, $table, $render_options)
{

// Add rowspan-attributes to table header cells in rendered HTML output
// TablePress-specific assumptions:
// - There is only one row (<tr></tr>) in table header (<thead></thead>).
function tablepress_ext_rowspan_all_adjust_html($output, $table, $render_options) {
// table
$table = fragment_to_dom($output);
$dom = $table->ownerDocument;
$xpath = new DOMXpath($dom);

// tablepress-specific assumptions:
// - there is only one row (<tr></tr>) in table header (<thead></thead>)


// thead
$theads = $xpath->query('//thead');
if ($theads->length === 0)
return $output; // skip
$thead = $theads->item(0);

$thead_row = $thead->getElementsByTagName('tr')->item(0);
$thead_cells = $thead_row->getElementsByTagName('th');
// thead cells can also have colspan
// physical occupation map


// thead cells can also have colspans
$thead_cells_phys = array();
foreach ($thead_cells as $thead_cell_index => $thead_cell) {
$thead_cells_phys[] = $thead_cell_index; // add at least once

$thead_cell_colspan = $thead_cell->getAttribute('colspan');
if (empty($thead_cell_colspan))
continue; // skip cell
for ($cs = 0; $cs < ($thead_cell_colspan - 1); $cs++)
$thead_cells_phys[] = $thead_cell_index;
$colspan_val = $thead_cell->getAttribute('colspan');
$colspan = !empty($colspan_val) ? $colspan_val : 1; // default colspan = 1

for($ins_col = 0; $ins_col < $colspan; $ins_col++)
$thead_cells_phys[] = $thead_cell_index - 1; // 0-based index!
}

// all rowspan marked cells
$trigger_cells = $xpath->query(".//td[not(ancestor::thead) and " . "not(ancestor::tfoot) and " . "text() = '" . TABLEPRESS_ROWSPAN_OUTSIDE . "']");



// all cells in table body that contain the outside-rowspan trigger word text,
// sorted by their order in DOM, row order is preserved
$trigger_cells = $xpath->query(".//td[not(ancestor::thead) and not(ancestor::tfoot) and text() = '" . TABLEPRESS_ROWSPAN_OUTSIDE . "']");

$last_row_no = 0;
foreach ($trigger_cells as $cell) {
// row of cell
$row = $xpath->query('parent::tr', $cell)->item(0);

// only continous rows after head (2nd test)
$row_no = dom_parent_position($row);
if ($row_no > ($last_row_no + 1))
if ($row_no > ($last_row_no + 1)) // when more than one row is skipped
continue;
$last_row_no = $row_no;
// find thead cell above this cell
$cell_no = dom_parent_position($cell);

// find thead cell above this cell (in same physical column)
$cell_no = dom_parent_position($cell); // cell no = column no
$thead_cell_phys_no = $thead_cells_phys[$cell_no];
$thead_cell = $thead_cells->item($thead_cell_phys_no);

// update rowspan of cell
$cur_rowspan = $thead_cell->getAttribute('rowspan');
if (!$cur_rowspan)
$cur_rowspan = 1;


// update rowspan of thead cell
$cur_rowspan_val = $thead_cell->getAttribute('rowspan');
$cur_rowspan = !empty($cur_rowspan_val) ? $cur_rowspan_val : 1; // default rowspan = 1

$thead_cell->setAttribute('rowspan', $cur_rowspan + 1);

// move row to thead
$thead->appendChild($row);
}

// remove the placeholder trigger word cells
// in second step because removal during iteration causes issues
foreach ($trigger_cells as $cell)


// The following manipulations change the DOM tree,
// this would intefere in the loop above,
// hence this is done in a separate step afterwards:

foreach ($trigger_cells as $cell) {
// move affected rows to thead
$row = $xpath->query('parent::tr', $cell)->item(0);
$thead->appendChild($row); // (idempotent)

// remove the placeholder trigger word cells
$cell->parentNode->removeChild($cell);

}

// change td to th for the new row
$thead_td_cells = $xpath->query('.//td', $thead);
foreach ($thead_td_cells as $td_cell)
$changed_th_cell = dom_change_tagname($td_cell, 'th');


$newHtml = dom_to_fragment($table);
return $newHtml;
}, 3, 10);
}
add_filter('tablepress_table_output', 'tablepress_ext_rowspan_all_adjust_html', 3, 10);

0 comments on commit 80ef3ec

Please sign in to comment.