Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions classes/helpers/FrmListHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1041,8 +1041,12 @@ public function print_column_headers( $with_id = true ) { // phpcs:ignore Slevom
);
}//end if

$tag = 'cb' === $column_key ? 'td' : 'th';
$scope = 'th' === $tag ? 'scope="col"' : '';
// The cb column's row cells are already `<th scope="row">` (see column_cb()), so make its header cell
// a matching `<th scope="col">` instead of a headerless `<td>` (IBM table_headers_exists). A `scope`
// attribute on a `<td>` isn't recognized as a header by assistive tech, so this needs a real `<th>` -
// see _widefat.scss for the matching CSS to keep the cell's layout unchanged.
$tag = 'th';
$scope = 'scope="col"';
$id = $with_id ? "id='" . esc_attr( $column_key ) . "'" : '';

if ( $class ) {
Expand Down Expand Up @@ -1078,11 +1082,12 @@ public function display( $args = array() ) {
$this->display_tablenav( 'top' );
}
$this->screen->render_screen_reader_content( 'heading_list' );
$has_headers = $this->has_min_items( 1 );

// phpcs:disable Generic.WhiteSpace.ScopeIndent
?>
<table class="wp-list-table <?php echo esc_attr( implode( ' ', $this->get_table_classes() ) ); ?>">
<?php if ( $this->has_min_items( 1 ) ) { ?>
<table class="wp-list-table <?php echo esc_attr( implode( ' ', $this->get_table_classes() ) ); ?>"<?php echo $has_headers ? '' : ' role="presentation"'; ?>>
<?php if ( $has_headers ) { ?>
<thead>
<tr>
<?php $this->print_column_headers(); ?>
Expand All @@ -1094,7 +1099,7 @@ public function display( $args = array() ) {
<?php $this->display_rows_or_placeholder(); ?>
</tbody>

<?php if ( $this->has_min_items( 1 ) && $this->should_display( $args, 'display-bottom-headers' ) ) { ?>
<?php if ( $has_headers && $this->should_display( $args, 'display-bottom-headers' ) ) { ?>
<tfoot>
<tr>
<?php $this->print_column_headers( false ); ?>
Expand Down
14 changes: 7 additions & 7 deletions classes/views/xml/import_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@
<table class="widefat striped frm-border frm-mt-0">
<thead>
<tr>
<td class="column-cb check-column">
<th scope="col" class="column-cb check-column">
<label class="screen-reader-text" for="frm-export-select-all"><?php esc_html_e( 'Select All', 'formidable' ); ?></label>
<input id="frm-export-select-all" type="checkbox">
</td>
<td><?php esc_html_e( 'Form Title', 'formidable' ); ?></td>
<td><?php esc_html_e( 'ID / Form Key', 'formidable' ); ?></td>
<td><?php esc_html_e( 'Type', 'formidable' ); ?></td>
<td class="column-entries"><?php esc_html_e( 'Entries', 'formidable' ); ?></td>
<td class="column-entries"><?php esc_html_e( 'Style', 'formidable' ); ?></td>
</th>
<th scope="col"><?php esc_html_e( 'Form Title', 'formidable' ); ?></th>
<th scope="col"><?php esc_html_e( 'ID / Form Key', 'formidable' ); ?></th>
<th scope="col"><?php esc_html_e( 'Type', 'formidable' ); ?></th>
<th scope="col" class="column-entries"><?php esc_html_e( 'Entries', 'formidable' ); ?></th>
<th scope="col" class="column-entries"><?php esc_html_e( 'Style', 'formidable' ); ?></th>
</tr>
</thead>
<tbody>
Expand Down
4 changes: 2 additions & 2 deletions css/frm_admin.css

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions resources/scss/admin/components/table/_widefat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@
font-size: var(--text-md);
}

// FrmListHelper::print_column_headers() (Forms/Entries lists) and the Export table
// (classes/views/xml/import_form.php) both render their cb column header as a <th>, not
// core's <td>; the .frm-white-body rule above would otherwise grow it past core's
// check-column sizing, so restate core's font-size/padding here to keep that cell's layout
// unchanged. Scoped to table.widefat (shared by both tables) rather than .wp-list-table,
// which the Export table's own <table> doesn't carry.
table.widefat thead th.check-column,
table.widefat tfoot th.check-column {
font-size: var(--text-sm);
padding: 4px 0 0 3px;
vertical-align: middle;
}

.frm-white-body table.widefat th a {
color: var(--grey-700);
}
Expand Down
8 changes: 8 additions & 0 deletions resources/scss/admin/media-queries/_screen-tablet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@
width: 1.2rem;
height: 1.2rem;
}

// Matches core's own td.check-column padding-top at this breakpoint (list-tables.css) -
// see the desktop override in _widefat.scss for why this cell is a <th> here, not core's
// <td>, and for why this is scoped to table.widefat rather than .wp-list-table.
table.widefat thead th.check-column,
table.widefat tfoot th.check-column {
padding-top: 10px;
}
}

@media only screen and (max-width: 700px) {
Expand Down
35 changes: 35 additions & 0 deletions tests/phpunit/forms/test_FrmFormsListHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,39 @@ public function test_get_posts_contain_form() {
$this->assertContains( $post_with_form, $post_ids );
$this->assertNotContains( $post_without_form, $post_ids );
}

/**
* @covers FrmFormsListHelper::print_column_headers
*/
public function test_checkbox_column_header_is_th() {
$this->set_user_by_role( 'administrator' );
$this->set_admin_screen( 'admin.php?page=formidable' );
FrmFormsController::maybe_load_listing_hooks();

// Prime WP core's per-screen `get_column_headers()` cache the same way admin-header.php's
// Screen Options rendering does in a real page load, before the list table's own instance
// filter is registered - otherwise that instance filter (a back-compat no-op) runs second
// and wipes the controller's real columns back to an empty array.
get_column_headers( 'toplevel_page_formidable' );

$list_helper = new FrmFormsListHelper(
array(
'params' => FrmForm::get_admin_params( 0 ),
'screen' => 'toplevel_page_formidable',
)
);
$list_helper->prepare_items();

ob_start();
$list_helper->display();
$html = ob_get_clean();

$thead = substr( $html, 0, strpos( $html, '</thead>' ) );

$this->assertMatchesRegularExpression(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsListHelper::assertMatchesRegularExpression()


The method you are trying to call is not defined, which can result in a fatal error.

'/<th[^>]*scope="col"[^>]*id=[\'"]cb[\'"][^>]*>/',
$thead,
'The cb column header cell must be a real <th scope="col">, not a <td>, for IBM table_headers_exists.'
);
}
}
20 changes: 20 additions & 0 deletions tests/phpunit/xml/test_FrmXMLController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,24 @@ public function test_validate_xml_url() {
private function validate_xml_url( $url ) {
return $this->run_private_method( array( 'FrmXMLController', 'validate_xml_url' ), array( $url ) );
}

/**
* @covers FrmXMLController::form
*/
public function test_export_table_headers_are_th() {
$this->set_user_by_role( 'administrator' );

ob_start();
FrmXMLController::form();
$html = ob_get_clean();

$thead = substr( $html, strpos( $html, '<thead>' ), strpos( $html, '</thead>' ) - strpos( $html, '<thead>' ) );

$this->assertStringContainsString(
'<th scope="col" class="column-cb check-column">',
$thead,
'The Export table\'s cb column header cell must be a real <th scope="col">, not a <td>, for IBM table_headers_exists.'
);
$this->assertStringNotContainsString( '<td', $thead );
}
}
Loading