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-editor-button-thickbox-list-table.php +73 -39 2.1.8 → 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 * Initializes the List Table.
34 35 *
@@ -34,8 +35,9 @@
34 35 *
35 36 * @since 1.0.0
36 37 */
37 38 public function __construct() {
39 + // @phpstan-ignore argument.type (WordPress Core's docblocks state wrong argument types in some places.)
38 40 parent::__construct( array(
39 41 'singular' => 'tablepress-table', // Singular name of the listed records.
40 42 'plural' => 'tablepress-editor-button-list', // Plural name of the listed records.
41 43 'ajax' => false, // Does this list table support AJAX?
@@ -47,11 +49,11 @@
47 49 * Sets the data items (here: tables) that are to be displayed by the List Tables, and their original count.
48 50 *
49 51 * @since 1.0.0
50 52 *
51 - * @param array $items Tables to be displayed in the List Table.
53 + * @param string[] $items Tables to be displayed in the List Table.
52 54 */
53 - public function set_items( array $items ) {
55 + public function set_items( array $items ): void {
54 56 $this->items = $items;
55 57 $this->items_count = count( $items );
56 58 }
57 59
@@ -62,9 +64,10 @@
62 64 * @since 1.0.0
63 65 *
64 66 * @return bool true (Default value).
65 67 */
66 - public function ajax_user_can() {
68 + #[\Override]
69 + public function ajax_user_can(): bool {
67 70 return true;
68 71 }
69 72
70 73 /**
@@ -73,11 +76,12 @@
73 76 * Format: 'internal-name' => 'Column Title'.
74 77 *
75 78 * @since 1.0.0
76 79 *
77 - * @return array List of columns in this List Table.
80 + * @return array<string, string> List of columns in this List Table.
78 81 */
79 - public function get_columns() {
82 + #[\Override]
83 + public function get_columns(): array {
80 84 $columns = array(
81 85 // "name" is special in WP, which is why we prefix every entry here, to be safe!
82 86 'table_id' => __( 'ID', 'tablepress' ),
83 87 'table_name' => __( 'Table Name', 'tablepress' ),
@@ -93,11 +97,12 @@
93 97 * Format: 'internal-name' => array( $field for $item[ $field ], true for already sorted ).
94 98 *
95 99 * @since 1.0.0
96 100 *
97 - * @return array List of sortable columns in this List Table.
101 + * @return array<string, array{string, bool}> List of sortable columns in this List Table.
98 102 */
99 - protected function get_sortable_columns() {
103 + #[\Override]
104 + protected function get_sortable_columns(): array {
100 105 // No sorting on the Empty List placeholder.
101 106 if ( ! $this->has_items() ) {
102 107 return array();
103 108 }
@@ -116,9 +121,10 @@
116 121 * @since 1.7.0
117 122 *
118 123 * @return string Name of the default primary column, in this case, the table name.
119 124 */
120 - protected function get_default_primary_column_name() {
125 + #[\Override]
126 + protected function get_default_primary_column_name(): string {
121 127 return 'table_name';
122 128 }
123 129
124 130 /**
@@ -125,24 +131,41 @@
125 131 * Renders a cell in the "table_id" column.
126 132 *
127 133 * @since 1.0.0
128 134 *
129 - * @param array $item Data item for the current row.
135 + * @param array<string, mixed> $item Data item for the current row.
130 136 * @return string HTML content of the cell.
131 137 */
132 - protected function column_table_id( array $item ) {
138 + protected function column_table_id( array $item ): string {
133 139 return esc_html( $item['id'] );
134 140 }
135 141
136 142 /**
143 + * Returns a clean label for the primary (Table Name) column's row header `aria-label`.
144 + *
145 + * Provides screen readers with just the table name as the row header name,
146 + * preventing them from computing the name from the full cell content.
147 + *
148 + * @since 3.3.4
149 + *
150 + * @param array<string, mixed> $item Data item for the current row.
151 + * @return string The table name.
152 + */
153 + protected function get_primary_column_aria_label( /* array */ $item ): string {
154 + // Don't use type hints in the method declaration to prevent PHP errors, as the method is inherited.
155 +
156 + return trim( $item['name'] );
157 + }
158 +
159 + /**
137 160 * Renders a cell in the "table_name" column.
138 161 *
139 162 * @since 1.0.0
140 163 *
141 - * @param array $item Data item for the current row.
164 + * @param array<string, mixed> $item Data item for the current row.
142 165 * @return string HTML content of the cell.
143 166 */
144 - protected function column_table_name( array $item ) {
167 + protected function column_table_name( array $item ): string {
145 168 if ( '' === trim( $item['name'] ) ) {
146 169 $item['name'] = __( '(no name)', 'tablepress' );
147 170 }
148 171 return esc_html( $item['name'] );
@@ -152,12 +175,12 @@
152 175 * Renders a cell in the "table_description" column.
153 176 *
154 177 * @since 1.0.0
155 178 *
156 - * @param array $item Data item for the current row.
179 + * @param array<string, mixed> $item Data item for the current row.
157 180 * @return string HTML content of the cell.
158 181 */
159 - protected function column_table_description( array $item ) {
182 + protected function column_table_description( array $item ): string {
160 183 if ( '' === trim( $item['description'] ) ) {
161 184 $item['description'] = __( '(no description)', 'tablepress' );
162 185 }
163 186 return esc_html( $item['description'] );
@@ -167,13 +190,13 @@
167 190 * Renders a cell in the "table_action" column, i.e. the "Insert" link.
168 191 *
169 192 * @since 1.0.0
170 193 *
171 - * @param array $item Data item for the current row.
194 + * @param array<string, mixed> $item Data item for the current row.
172 195 * @return string HTML content of the cell.
173 196 */
174 - protected function column_table_action( array $item ) {
175 - return '<input type="button" class="insert-shortcode button" title="' . esc_attr( '[' . TablePress::$shortcode . " id={$item['id']} /]" ) . '" value="' . esc_attr__( 'Insert Shortcode', 'tablepress' ) . '" />';
197 + protected function column_table_action( array $item ): string {
198 + return '<input type="button" class="insert-shortcode button button-compact" title="' . esc_attr( '[' . TablePress::$shortcode . " id={$item['id']} /]" ) . '" value="' . esc_attr__( 'Insert Shortcode', 'tablepress' ) . '">';
176 199 }
177 200
178 201 /**
179 202 * Holds the message to be displayed when there are no items in the table.
@@ -179,9 +202,10 @@
179 202 * Holds the message to be displayed when there are no items in the table.
180 203 *
181 204 * @since 1.0.0
182 205 */
183 - public function no_items() {
206 + #[\Override]
207 + public function no_items(): void {
184 208 _e( 'No tables found.', 'tablepress' );
185 209 if ( 0 === $this->items_count ) {
186 210 echo ' ' . __( 'You should add or import a table on the TablePress screens to get started!', 'tablepress' );
187 211 }
@@ -193,11 +217,14 @@
193 217 * In comparison with parent class, this has modified HTML (no nonce field), and a check whether there are items.
194 218 *
195 219 * @since 1.0.0
196 220 *
197 - * @param string $which Location ("top" or "bottom").
221 + * @param 'top'|'bottom' $which Location ("top" or "bottom").
198 222 */
199 - protected function display_tablenav( $which ) {
223 + #[\Override]
224 + protected function display_tablenav( /* string */ $which ): void {
225 + // Don't use type hints in the method declaration to prevent PHP errors, as the method is inherited.
226 +
200 227 if ( ! $this->has_items() ) {
201 228 return;
202 229 }
203 230 ?>
@@ -209,11 +236,11 @@
209 236 $this->extra_tablenav( $which );
210 237
211 238 add_filter( 'ngettext_default', array( $this, 'change_pagination_items_string' ), 10, 5 );
212 239 $this->pagination( $which );
213 - remove_filter( 'ngettext_default', array( $this, 'change_pagination_items_string' ), 10, 5 );
240 + remove_filter( 'ngettext_default', array( $this, 'change_pagination_items_string' ), 10 );
214 241 ?>
215 - <br class="clear" />
242 + <br class="clear">
216 243 </div>
217 244 <?php
218 245 }
219 246
@@ -228,10 +255,11 @@
228 255 * @param int $number The number to compare against to use either the singular or plural form.
229 256 * @param string $domain Text domain. Defaults to 'default'.
230 257 * @return string The changed translation.
231 258 */
232 - public function change_pagination_items_string( $translation, $single, $plural, $number, $domain ) {
259 + public function change_pagination_items_string( string $translation, string $single, string $plural, int $number, string $domain ): string {
233 260 if ( '%s item' === $single && '%s items' === $plural ) {
261 + /* translators: %s: Number of tables */
234 262 $translation = _n( '%s table', '%s tables', $number, 'tablepress' );
235 263 }
236 264 return $translation;
237 265 }
@@ -243,31 +271,37 @@
243 271 *
244 272 * @param string $item Table ID that shall be searched.
245 273 * @return bool Whether the search term was found or not.
246 274 */
247 - protected function _search_callback( $item ) {
275 + protected function _search_callback( string $item ): bool {
248 276 static $term;
249 277 static $json_encoded_term;
250 278 if ( is_null( $term ) || is_null( $json_encoded_term ) ) {
251 279 $term = wp_unslash( $_GET['s'] );
252 - $json_encoded_term = substr( wp_json_encode( $term, TABLEPRESS_JSON_OPTIONS ), 1, -1 );
280 + $json_encoded_term = substr( wp_json_encode( $term, TABLEPRESS_JSON_OPTIONS ), 1, -1 ); // @phpstan-ignore argument.type
253 281 }
254 282
255 283 // Load table again, with table data, but without options and visibility settings.
256 284 $item = TablePress::$model_table->load( $item, true, false );
257 285
286 + if ( is_wp_error( $item ) ) {
287 + return false;
288 + }
289 +
258 290 // Don't search corrupted tables.
259 291 if ( isset( $item['is_corrupted'] ) && $item['is_corrupted'] ) {
260 292 return false;
261 293 }
262 294
295 + $fn_stripos = function_exists( 'mb_stripos' ) ? 'mb_stripos' : 'stripos';
296 +
263 297 // Search from easy to hard, so that "expensive" code maybe doesn't have to run.
264 - if ( false !== stripos( $item['id'], $term )
265 - || false !== stripos( $item['name'], $term )
266 - || false !== stripos( $item['description'], $term )
267 - || false !== stripos( TablePress::get_user_display_name( $item['author'] ), $term )
268 - || false !== stripos( TablePress::format_datetime( $item['last_modified'] ), $term )
269 - || false !== stripos( wp_json_encode( $item['data'], TABLEPRESS_JSON_OPTIONS ), $json_encoded_term ) ) {
298 + if ( false !== $fn_stripos( $item['id'], (string) $term )
299 + || false !== $fn_stripos( $item['name'], (string) $term )
300 + || false !== $fn_stripos( $item['description'], (string) $term )
301 + || false !== $fn_stripos( TablePress::get_user_display_name( $item['author'] ), (string) $term )
302 + || false !== $fn_stripos( TablePress::format_datetime( $item['last_modified'] ), (string) $term )
303 + || false !== $fn_stripos( wp_json_encode( $item['data'], TABLEPRESS_JSON_OPTIONS ), (string) $json_encoded_term ) ) { // @phpstan-ignore argument.type
270 304 return true;
271 305 }
272 306
273 307 return false;
@@ -277,13 +311,13 @@
277 311 * Callback to for the array sort function.
278 312 *
279 313 * @since 1.0.0
280 314 *
281 - * @param array $item_a First item that shall be compared to.
282 - * @param array $item_b The second item for the comparison.
315 + * @param array<string, mixed> $item_a First item that shall be compared to.
316 + * @param array<string, mixed> $item_b The second item for the comparison.
283 317 * @return int (-1, 0, 1) depending on which item sorts "higher".
284 318 */
285 - protected function _order_callback( array $item_a, array $item_b ) {
319 + protected function _order_callback( array $item_a, array $item_b ): int {
286 320 global $orderby, $order;
287 321
288 322 if ( $item_a[ $orderby ] === $item_b[ $orderby ] ) {
289 323 return 0;
@@ -299,9 +333,10 @@
299 333 * Prepares the list of items for displaying, by maybe searching and sorting, and by doing pagination.
300 334 *
301 335 * @since 1.0.0
302 336 */
303 - public function prepare_items() {
337 + #[\Override]
338 + public function prepare_items(): void {
304 339 global $orderby, $order, $s;
305 340 wp_reset_vars( array( 'orderby', 'order', 's' ) );
306 341
307 342 // Maybe search in the items.
@@ -313,10 +348,9 @@
313 348 foreach ( $this->items as &$item ) {
314 349 // Don't load data nor table options.
315 350 $item = TablePress::$model_table->load( $item, false, false );
316 351 }
317 - // Break reference in foreach iterator.
318 - unset( $item );
352 + unset( $item ); // Unset use-by-reference parameter of foreach loop.
319 353
320 354 // Maybe sort the items.
321 355 $_sortable_columns = $this->get_sortable_columns();
322 356 if ( $orderby && ! empty( $this->items ) && isset( $_sortable_columns[ "table_{$orderby}" ] ) ) {