PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
← All changes | views/class-all-tables-list-table.php +55 -29 2.3.2 → 3.4 View file →
@@ -7,8 +7,10 @@
7 7 * @author Tobias Bäthge
8 8 * @since 2.0.0
9 9 */
10 10
11 +declare(strict_types=1);
12 +
11 13 // Prohibit direct script loading.
12 14 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13 15
14 16 /**
@@ -24,11 +26,10 @@
24 26 /**
25 27 * Number of items of the initial data set (before sort, search, and pagination).
26 28 *
27 29 * @since 1.0.0
28 - * @var int
29 30 */
30 - protected $items_count = 0;
31 + protected int $items_count = 0;
31 32
32 33 /**
33 34 * Cached bulk actions.
34 35 *
@@ -35,11 +36,11 @@
35 36 * This property has to be declared here, as it's `private` in the parent class
36 37 * and thus can't be inherited.
37 38 *
38 39 * @since 1.0.0
39 - * @var array<string, string>|null
40 + * @var array<string, string>
40 41 */
41 - protected $_actions; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
42 + protected array $_actions; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
42 43
43 44 /**
44 45 * Initialize the List Table.
45 46 *
@@ -48,13 +49,13 @@
48 49 public function __construct() {
49 50 $screen = get_current_screen();
50 51
51 52 // Hide "Last Modified By" column by default.
52 - if ( false === get_user_option( "manage{$screen->id}columnshidden" ) ) {
53 - update_user_option( get_current_user_id(), "manage{$screen->id}columnshidden", array( 'table_last_modified_by' ), true );
53 + if ( false === get_user_option( "manage{$screen->id}columnshidden" ) ) { // @phpstan-ignore property.nonObject
54 + update_user_option( get_current_user_id(), "manage{$screen->id}columnshidden", array( 'table_last_modified_by' ), true ); // @phpstan-ignore property.nonObject
54 55 }
55 56
56 - // @phpstan-ignore-next-line (WordPress Core's docblocks state wrong argument types in some places.)
57 + // @phpstan-ignore argument.type (WordPress Core's docblocks state wrong argument types in some places.)
57 58 parent::__construct( array(
58 59 'singular' => 'tablepress-table', // Singular name of the listed records.
59 60 'plural' => 'tablepress-all-tables', // Plural name of the listed records.
60 61 'ajax' => false, // Does this list table support AJAX?
@@ -98,9 +99,9 @@
98 99 */
99 100 #[\Override]
100 101 public function get_columns(): array {
101 102 $columns = array(
102 - 'cb' => $this->has_items() ? '<input type="checkbox" />' : '', // Checkbox for "Select all", but only if there are items in the table.
103 + 'cb' => $this->has_items() ? '<input type="checkbox">' : '', // Checkbox for "Select all", but only if there are items in the table.
103 104 // "name" is special in WP, which is why we prefix every entry here, to be safe!
104 105 'table_id' => __( 'ID', 'tablepress' ),
105 106 'table_name' => __( 'Table Name', 'tablepress' ),
106 107 'table_description' => __( 'Description', 'tablepress' ),
@@ -174,12 +175,11 @@
174 175 $item['name'] = __( '(no name)', 'tablepress' );
175 176 }
176 177
177 178 return sprintf(
178 - // The `label-covers-full-cell` class on the <label> is kept for (some) backward compatibility with WordPress 6.3, and can be removed once TablePress requires WordPress 6.4.
179 - '<input type="checkbox" id="cb-select-%1$s" name="table[]" value="%1$s" /><label class="label-covers-full-cell" for="cb-select-%1$s"><span class="screen-reader-text">%2$s</span></label>',
179 + '<input type="checkbox" id="cb-select-%1$s" name="table[]" value="%1$s"><label for="cb-select-%1$s"><span class="screen-reader-text">%2$s</span></label>',
180 180 esc_attr( $item['id'] ),
181 - esc_html( sprintf( __( 'Select table “%s”', 'tablepress' ), $item['name'] ) )
181 + esc_html( sprintf( __( 'Select table “%s”', 'tablepress' ), $item['name'] ) ),
182 182 );
183 183 }
184 184
185 185 /**
@@ -194,8 +194,25 @@
194 194 return esc_html( $item['id'] );
195 195 }
196 196
197 197 /**
198 + * Returns a clean label for the primary (Table Name) column's row header `aria-label`.
199 + *
200 + * Provides screen readers with just the table name as the row header name,
201 + * preventing them from computing the name from the full cell content.
202 + *
203 + * @since 3.3.4
204 + *
205 + * @param array<string, mixed> $item Data item for the current row.
206 + * @return string The table name.
207 + */
208 + protected function get_primary_column_aria_label( /* array */ $item ): string {
209 + // Don't use type hints in the method declaration to prevent PHP errors, as the method is inherited.
210 +
211 + return trim( $item['name'] );
212 + }
213 +
214 + /**
198 215 * Render a cell in the "table_name" column.
199 216 *
200 217 * @since 1.0.0
201 218 *
@@ -236,9 +253,9 @@
236 253 if ( $user_can_export_table ) {
237 254 $row_actions['export'] = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $export_url, esc_attr( sprintf( __( 'Export &#8220;%s&#8221;', 'tablepress' ), $item['name'] ) ), _x( 'Export', 'row action', 'tablepress' ) );
238 255 }
239 256 if ( $user_can_delete_table ) {
240 - $row_actions['delete'] = sprintf( '<a href="%1$s" title="%2$s" class="delete-link">%3$s</a>', $delete_url, esc_attr( sprintf( __( 'Delete &#8220;%s&#8221;', 'tablepress' ), $item['name'] ) ), __( 'Delete', 'tablepress' ) );
257 + $row_actions['delete'] = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $delete_url, esc_attr( sprintf( __( 'Delete “%1$s” (ID %2$s)', 'tablepress' ), $item['name'], $item['id'] ) ), __( 'Delete', 'tablepress' ) );
241 258 }
242 259 if ( $user_can_preview_table ) {
243 260 $row_actions['table-preview'] = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $preview_url, esc_attr( sprintf( __( 'Preview of table “%1$s” (ID %2$s)', 'tablepress' ), $item['name'], $item['id'] ) ), __( 'Preview', 'tablepress' ) );
244 261 }
@@ -294,9 +311,13 @@
294 311 * @return string HTML content of the cell.
295 312 */
296 313 protected function column_table_last_modified( array $item ): string {
297 314 $modified_timestamp = date_create( $item['last_modified'], wp_timezone() );
298 - $modified_timestamp = $modified_timestamp->getTimestamp(); // @phpstan-ignore-line
315 + if ( false === $modified_timestamp ) {
316 + $modified_timestamp = $item['last_modified'];
317 + } else {
318 + $modified_timestamp = $modified_timestamp->getTimestamp();
319 + }
299 320 $current_timestamp = time();
300 321 $time_diff = $current_timestamp - $modified_timestamp;
301 322 // Time difference is only shown up to one week.
302 323 if ( $time_diff >= 0 && $time_diff < WEEK_IN_SECONDS ) {
@@ -301,9 +322,9 @@
301 322 // Time difference is only shown up to one week.
302 323 if ( $time_diff >= 0 && $time_diff < WEEK_IN_SECONDS ) {
303 324 $time_diff = sprintf( __( '%s ago', 'default' ), human_time_diff( $modified_timestamp, $current_timestamp ) );
304 325 } else {
305 - $time_diff = TablePress::format_datetime( $item['last_modified'], '<br />' );
326 + $time_diff = TablePress::format_datetime( $item['last_modified'], '<br>' );
306 327 }
307 328 $readable_time = TablePress::format_datetime( $item['last_modified'] );
308 329 return '<abbr title="' . esc_attr( $readable_time ) . '">' . $time_diff . '</abbr>';
309 330 }
@@ -387,9 +408,9 @@
387 408 #[\Override]
388 409 protected function bulk_actions( /* string */ $which = 'top' ): void {
389 410 // Don't use type hints in the method declaration to prevent PHP errors, as the method is inherited.
390 411
391 - if ( is_null( $this->_actions ) ) {
412 + if ( ! isset( $this->_actions ) ) {
392 413 $this->_actions = $this->get_bulk_actions();
393 414 $no_new_actions = $this->_actions;
394 415 /** This filter is documented in the WordPress function WP_List_Table::bulk_actions() in wp-admin/includes/class-wp-list-table.php */
395 416 $this->_actions = apply_filters( 'bulk_actions-' . $this->screen->id, $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
@@ -403,16 +424,19 @@
403 424 return;
404 425 }
405 426
406 427 $name_id = "bulk-action-selector-{$which}";
407 - echo "<label for='{$name_id}' class='screen-reader-text'>" . __( 'Select Bulk Action', 'tablepress' ) . "</label>\n";
428 + echo "<label for='{$name_id}' class='screen-reader-text'>" .
429 + /* translators: Hidden accessibility text. */
430 + __( 'Select bulk action', 'default' ) .
431 + '</label>';
408 432 echo "<select name='{$name_id}' id='{$name_id}'>\n";
409 - echo "<option value='-1' selected='selected'>" . __( 'Bulk Actions', 'tablepress' ) . "</option>\n";
433 + echo "<option value='-1' selected='selected'>" . __( 'Bulk actions', 'default' ) . "</option>\n";
410 434 foreach ( $this->_actions as $name => $title ) {
411 435 echo "\t<option value='{$name}'>{$title}</option>\n";
412 436 }
413 437 echo "</select>\n";
414 - submit_button( __( 'Apply', 'tablepress' ), 'action', '', false, array( 'id' => "doaction{$two}" ) );
438 + submit_button( __( 'Apply', 'default' ), 'action', 'bulk_action', false, array( 'id' => "doaction{$two}" ) );
415 439 echo "\n";
416 440 }
417 441
418 442 /**
@@ -468,9 +492,9 @@
468 492 $this->pagination( $which );
469 493 remove_filter( 'ngettext_default', array( $this, 'change_pagination_items_string' ), 10 );
470 494 ?>
471 495
472 - <br class="clear" />
496 + <br class="clear">
473 497 </div>
474 498 <?php
475 499 }
476 500
@@ -487,8 +511,9 @@
487 511 * @return string The changed translation.
488 512 */
489 513 public function change_pagination_items_string( string $translation, string $single, string $plural, int $number, string $domain ): string {
490 514 if ( '%s item' === $single && '%s items' === $plural ) {
515 + /* translators: %s: Number of tables */
491 516 $translation = _n( '%s table', '%s tables', $number, 'tablepress' );
492 517 }
493 518 return $translation;
494 519 }
@@ -505,9 +530,9 @@
505 530 static $term;
506 531 static $json_encoded_term;
507 532 if ( is_null( $term ) || is_null( $json_encoded_term ) ) {
508 533 $term = wp_unslash( $_GET['s'] );
509 - $json_encoded_term = substr( wp_json_encode( $term, TABLEPRESS_JSON_OPTIONS ), 1, -1 ); // @phpstan-ignore-line
534 + $json_encoded_term = substr( wp_json_encode( $term, TABLEPRESS_JSON_OPTIONS ), 1, -1 ); // @phpstan-ignore argument.type
510 535 }
511 536
512 537 static $debug;
513 538 if ( is_null( $debug ) ) {
@@ -526,16 +551,18 @@
526 551 if ( ! $debug && isset( $item['is_corrupted'] ) && $item['is_corrupted'] ) {
527 552 return false;
528 553 }
529 554
555 + $fn_stripos = function_exists( 'mb_stripos' ) ? 'mb_stripos' : 'stripos';
556 +
530 557 // Search from easy to hard, so that "expensive" code maybe doesn't have to run.
531 - if ( false !== stripos( $item['id'], $term )
532 - || false !== stripos( $item['name'], $term )
533 - || false !== stripos( $item['description'], $term )
534 - || false !== stripos( TablePress::get_user_display_name( $item['author'] ), $term )
535 - || false !== stripos( TablePress::get_user_display_name( $item['options']['last_editor'] ), $term )
536 - || false !== stripos( TablePress::format_datetime( $item['last_modified'] ), $term )
537 - || false !== stripos( wp_json_encode( $item['data'], TABLEPRESS_JSON_OPTIONS ), $json_encoded_term ) ) { // @phpstan-ignore-line
558 + if ( false !== $fn_stripos( $item['id'], (string) $term )
559 + || false !== $fn_stripos( $item['name'], (string) $term )
560 + || false !== $fn_stripos( $item['description'], (string) $term )
561 + || false !== $fn_stripos( TablePress::get_user_display_name( $item['author'] ), (string) $term )
562 + || false !== $fn_stripos( TablePress::get_user_display_name( $item['options']['last_editor'] ), (string) $term )
563 + || false !== $fn_stripos( TablePress::format_datetime( $item['last_modified'] ), (string) $term )
564 + || false !== $fn_stripos( wp_json_encode( $item['data'], TABLEPRESS_JSON_OPTIONS ), (string) $json_encoded_term ) ) { // @phpstan-ignore argument.type
538 565 return true;
539 566 }
540 567
541 568 return false;
@@ -604,10 +631,9 @@
604 631 foreach ( $this->items as &$item ) {
605 632 // Don't load data, but load table options for access to last_editor.
606 633 $item = TablePress::$model_table->load( $item, false, true );
607 634 }
608 - // Break reference in foreach iterator.
609 - unset( $item );
635 + unset( $item ); // Unset use-by-reference parameter of foreach loop.
610 636
611 637 // Maybe sort the items.
612 638 $_sortable_columns = $this->get_sortable_columns();
613 639 if ( $orderby && ! empty( $this->items ) && isset( $_sortable_columns[ "table_{$orderby}" ] ) ) {