PluginProbe
TablePress – Tables in WordPress made easy / 3.0
TablePress – Tables in WordPress made easy v3.0
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 2.4.4 All 44 releases
← All changes | classes/class-view.php +183 -113 1.123.0 View file →
@@ -12,8 +12,9 @@
12 12 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13 13
14 14 /**
15 15 * TablePress Base View class
16 + *
16 17 * @package TablePress
17 18 * @subpackage Views
18 19 * @author Tobias Bäthge
19 20 * @since 1.0.0
@@ -23,51 +24,48 @@
23 24 /**
24 25 * Data for the view.
25 26 *
26 27 * @since 1.0.0
27 - * @var array
28 + * @var array<string, mixed>
28 29 */
29 - protected $data = array();
30 + protected array $data = array();
30 31
31 32 /**
32 33 * Number of screen columns for post boxes.
33 34 *
34 35 * @since 1.0.0
35 - * @var int
36 36 */
37 - protected $screen_columns = 0;
37 + protected int $screen_columns = 0;
38 38
39 39 /**
40 40 * User action for this screen.
41 41 *
42 42 * @since 1.0.0
43 - * @var string
44 43 */
45 - protected $action = '';
44 + protected string $action = '';
46 45
47 46 /**
48 47 * Instance of the Admin Page Helper Class, with necessary functions.
49 48 *
50 49 * @since 1.0.0
51 - * @var TablePress_Admin_Page
52 50 */
53 - protected $admin_page;
51 + protected \TablePress_Admin_Page $admin_page;
54 52
55 53 /**
56 54 * List of text boxes (similar to post boxes, but just with text and without extra functionality).
57 55 *
58 56 * @since 1.0.0
59 - * @var array
57 + * @var array<string, array<string, array<string, mixed>>>
60 58 */
61 - protected $textboxes = array();
59 + protected array $textboxes = array();
62 60
63 61 /**
64 62 * List of messages that are to be displayed as boxes below the page title.
65 63 *
66 64 * @since 1.0.0
67 - * @var array
65 + * @var string[]
68 66 */
69 - protected $header_messages = array();
67 + protected array $header_messages = array();
70 68
71 69 /**
72 70 * Whether there are post boxes registered for this screen,
73 71 * is automatically set to true, when a meta box is added.
@@ -72,19 +70,18 @@
72 70 * Whether there are post boxes registered for this screen,
73 71 * is automatically set to true, when a meta box is added.
74 72 *
75 73 * @since 1.0.0
76 - * @var bool
77 74 */
78 - protected $has_meta_boxes = false;
75 + protected bool $has_meta_boxes = false;
79 76
80 77 /**
81 78 * List of WP feature pointers for this view.
82 79 *
83 80 * @since 1.0.0
84 - * @var array
81 + * @var string[]
85 82 */
86 - protected $wp_pointers = array();
83 + protected array $wp_pointers = array();
87 84
88 85 /**
89 86 * Initialize the View class, by setting the correct screen columns and adding help texts.
90 87 *
@@ -92,25 +89,38 @@
92 89 */
93 90 public function __construct() {
94 91 $screen = get_current_screen();
95 92 if ( 0 !== $this->screen_columns ) {
96 - $screen->add_option( 'layout_columns', array( 'max' => $this->screen_columns ) );
93 + $screen->add_option( 'layout_columns', array( 'max' => $this->screen_columns ) ); // @phpstan-ignore method.nonObject
97 94 }
98 95 // Enable two column layout.
99 - add_filter( "get_user_option_screen_layout_{$screen->id}", array( $this, 'set_current_screen_layout_columns' ) );
96 + add_filter( "get_user_option_screen_layout_{$screen->id}", array( $this, 'set_current_screen_layout_columns' ) ); // @phpstan-ignore property.nonObject
100 97
101 - $screen->add_help_tab( array(
98 + $common_content = '<p>' . sprintf( __( 'More information about TablePress can be found on the <a href="%1$s">plugin website</a> or on its page in the <a href="%2$s">WordPress Plugin Directory</a>.', 'tablepress' ), 'https://tablepress.org/', 'https://wordpress.org/plugins/tablepress/' ) . '</p>';
99 + $common_content .= '<p>' . sprintf( __( 'For technical information, please see the <a href="%s">Documentation</a>.', 'tablepress' ), 'https://tablepress.org/documentation/' ) . ' ' . sprintf( __( 'Common questions are answered in the <a href="%s">FAQ</a>.', 'tablepress' ), 'https://tablepress.org/faq/' ) . '</p>';
100 +
101 + if ( tb_tp_fs()->is_free_plan() ) {
102 + $common_content .= '<p>'
103 + . sprintf( __( '<a href="%1$s">Support</a> is provided through the <a href="%2$s">WordPress Support Forums</a>.', 'tablepress' ), 'https://tablepress.org/support/', 'https://wordpress.org/tags/tablepress' )
104 + . ' '
105 + . sprintf( __( 'Before asking for support, please carefully read the <a href="%s">Frequently Asked Questions</a>, where you will find answers to the most common questions, and search through the forums.', 'tablepress' ), 'https://tablepress.org/faq/' )
106 + . '</p>';
107 + $common_content .= '<p><strong>' . sprintf( __( 'More great features for you and your site’s visitors and priority email support are available with a Premium license plan of TablePress. <a href="%s">Go check them out!</a>', 'tablepress' ), 'https://tablepress.org/premium/?utm_source=plugin&utm_medium=textlink&utm_content=help-tab' ) . '</strong></p>';
108 + }
109 +
110 + $screen->add_help_tab( array( // @phpstan-ignore method.nonObject
102 111 'id' => 'tablepress-help', // This should be unique for the screen.
103 112 'title' => __( 'TablePress Help', 'tablepress' ),
104 - 'content' => '<p>' . $this->help_tab_content() . '</p>'
105 - . '<p>' . sprintf( __( 'More information about TablePress can be found on the <a href="%1$s">plugin website</a> or on its page in the <a href="%2$s">WordPress Plugin Directory</a>.', 'tablepress' ), 'https://tablepress.org/', 'https://wordpress.org/plugins/tablepress/' ) . ' '
106 - . sprintf( __( 'For technical information, please see the <a href="%s">Documentation</a>.', 'tablepress' ), 'https://tablepress.org/documentation/' ) . ' '
107 - . sprintf( __( '<a href="%1$s">Support</a> is provided through the <a href="%2$s">WordPress Support Forums</a>.', 'tablepress' ), 'https://tablepress.org/support/', 'https://wordpress.org/tags/tablepress' ) . ' '
108 - . sprintf( __( 'Before asking for support, please carefully read the <a href="%s">Frequently Asked Questions</a>, where you will find answers to the most common questions, and search through the forums.', 'tablepress' ), 'https://tablepress.org/faq/' ) . '<br />'
109 - . sprintf( __( 'If you like the plugin, <a href="%1$s"><strong>a donation</strong></a> is recommended.', 'tablepress' ), 'https://tablepress.org/donate/' ) . '</p>',
113 + 'content' => '<p>' . $this->help_tab_content() . '</p>' . $common_content,
110 114 ) );
111 - // "sidebar" in the help tab.
112 - $screen->set_help_sidebar( '<p><strong>' . __( 'For more information:', 'tablepress' ) . '</strong></p><p><a href="https://tablepress.org/">TablePress Website</a></p><p><a href="https://tablepress.org/faq/">TablePress FAQ</a></p><p><a href="https://tablepress.org/documentation/">TablePress Documentation</a></p><p><a href="https://tablepress.org/support/">TablePress Support</a></p>' );
115 + // "Sidebar" in the help tab.
116 + $screen->set_help_sidebar( // @phpstan-ignore method.nonObject
117 + '<p><strong>' . __( 'For more information:', 'tablepress' ) . '</strong></p>'
118 + . '<p><a href="https://tablepress.org/">TablePress Website</a></p>'
119 + . '<p><a href="https://tablepress.org/faq/">TablePress FAQ</a></p>'
120 + . '<p><a href="https://tablepress.org/documentation/">TablePress Documentation</a></p>'
121 + . '<p><a href="https://tablepress.org/support/">TablePress Support</a></p>'
122 + );
113 123 }
114 124
115 125 /**
116 126 * Change the value of the user option "screen_layout_{$screen->id}" through a filter.
@@ -116,12 +126,12 @@
116 126 * Change the value of the user option "screen_layout_{$screen->id}" through a filter.
117 127 *
118 128 * @since 1.0.0
119 129 *
120 - * @param int|bool Current value of the user option.
130 + * @param int|false $result Current value of the user option.
121 131 * @return int New value for the user option.
122 132 */
123 - public function set_current_screen_layout_columns( $result ) {
133 + public function set_current_screen_layout_columns( /* int|false */ $result ): int {
124 134 if ( false === $result ) {
125 135 // The user option does not yet exist.
126 136 $result = $this->screen_columns;
127 137 } elseif ( $result > $this->screen_columns ) {
@@ -135,31 +145,28 @@
135 145 * Set up the view with data and do things that are necessary for all views.
136 146 *
137 147 * @since 1.0.0
138 148 *
139 - * @param string $action Action for this view.
140 - * @param array $data Data for this view.
149 + * @param string $action Action for this view.
150 + * @param array<string, mixed> $data Data for this view.
141 151 */
142 - public function setup( $action, array $data ) {
152 + public function setup( /* string */ $action, array $data ) /* : void */ {
153 + // Don't use type hints (except array $data) in method declaration, as the method is extended in some TablePress Extensions which are no longer updated.
154 +
143 155 $this->action = $action;
144 156 $this->data = $data;
145 157
146 158 // Set page title.
147 - $GLOBALS['title'] = sprintf( __( '%1$s &lsaquo; %2$s', 'tablepress' ), $this->data['view_actions'][ $this->action ]['page_title'], 'TablePress' );
159 + $GLOBALS['title'] = sprintf( __( '%1$s &lsaquo; %2$s', 'tablepress' ), $this->data['view_actions'][ $this->action ]['page_title'], 'TablePress' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
148 160
149 161 // Admin page helpers, like script/style loading, could be moved to view.
150 162 $this->admin_page = TablePress::load_class( 'TablePress_Admin_Page', 'class-admin-page-helper.php', 'classes' );
151 - $this->admin_page->enqueue_style( 'common' );
163 + $this->admin_page->enqueue_style( 'common', array( 'wp-components' ) );
152 164 // RTL styles for the admin interface.
153 165 if ( is_rtl() ) {
154 166 $this->admin_page->enqueue_style( 'common-rtl', array( 'tablepress-common' ) );
155 167 }
156 - $this->admin_page->enqueue_script( 'common', array( 'jquery', 'postbox' ), array(
157 - 'common' => array(
158 - 'ays_delete_single_table' => _n( 'Do you really want to delete this table?', 'Do you really want to delete these tables?', 1, 'tablepress' ),
159 - 'ays_delete_multiple_tables' => _n( 'Do you really want to delete this table?', 'Do you really want to delete these tables?', 2, 'tablepress' ),
160 - )
161 - ) );
168 + $this->admin_page->enqueue_script( 'common', array( 'jquery-core', 'postbox' ) );
162 169
163 170 $this->admin_page->add_admin_footer_text();
164 171
165 172 // Initialize WP feature pointers for TablePress.
@@ -175,23 +182,24 @@
175 182 * Register a header message for the view.
176 183 *
177 184 * @since 1.0.0
178 185 *
179 - * @param string $text Text for the header message.
180 - * @param string $class Optional. Additional CSS class for the header message.
181 - * @param string $title Optional. Text for the header title.
186 + * @param string $text Text for the header message.
187 + * @param string $css_class Optional. Additional CSS class for the header message.
188 + * @param string $title Optional. Text for the header title.
182 189 */
183 - protected function add_header_message( $text, $class = 'notice-success', $title = '' ) {
184 - if ( ! stripos( $class, 'not-dismissible' ) ) {
185 - $class .= ' is-dismissible';
190 + protected function add_header_message( string $text, string $css_class = 'notice-success', string $title = '' ): void {
191 + if ( ! str_contains( $css_class, 'not-dismissible' ) ) {
192 + $css_class .= ' is-dismissible';
186 193 }
187 - if ( ! empty( $title ) ) {
194 + if ( '' !== $title ) {
188 195 $title = "<h3>{$title}</h3>";
189 196 }
190 - if ( ! empty( $text ) ) {
197 + // Wrap the message text in HTML <p> tags if it does not already start with one (potentially with attributes), indicating custom message HTML.
198 + if ( '' !== $text && ! str_starts_with( $text, '<p' ) ) {
191 199 $text = "<p>{$text}</p>";
192 200 }
193 - $this->header_messages[] = "<div class=\"notice {$class}\">{$title}{$text}</div>\n";
201 + $this->header_messages[] = "<div class=\"notice {$css_class}\">{$title}{$text}</div>\n";
194 202 }
195 203
196 204 /**
197 205 * Process header action messages, i.e. check if a message should be added to the page.
@@ -197,14 +205,19 @@
197 205 * Process header action messages, i.e. check if a message should be added to the page.
198 206 *
199 207 * @since 1.0.0
200 208 *
201 - * @param array $action_messages Action messages for the screen.
209 + * @param array<string, string> $action_messages Action messages for the screen.
202 210 */
203 - protected function process_action_messages( array $action_messages ) {
211 + protected function process_action_messages( array $action_messages ): void {
204 212 if ( $this->data['message'] && isset( $action_messages[ $this->data['message'] ] ) ) {
205 - $class = ( 'error' === substr( $this->data['message'], 0, 5 ) ) ? 'notice-error' : 'notice-success';
206 - $this->add_header_message( "<strong>{$action_messages[ $this->data['message'] ]}</strong>", $class );
213 + $class = ( str_starts_with( $this->data['message'], 'error' ) ) ? 'notice-error' : 'notice-success';
214 +
215 + if ( '' !== $this->data['error_details'] ) {
216 + $this->data['error_details'] = '</p><p>' . sprintf( __( 'Error code: %s', 'tablepress' ), '<code>' . esc_html( $this->data['error_details'] ) . '</code>' );
217 + }
218 +
219 + $this->add_header_message( "<strong>{$action_messages[ $this->data['message'] ]}</strong>{$this->data['error_details']}", $class );
207 220 }
208 221 }
209 222
210 223 /**
@@ -212,13 +225,13 @@
212 225 *
213 226 * @since 1.0.0
214 227 *
215 228 * @param string $id Unique HTML ID for the text box container (only visible with $wrap = true).
216 - * @param callback $callback Callback that prints the contents of the text box.
229 + * @param callable $callback Callback that prints the contents of the text box.
217 230 * @param string $context Optional. Context/position of the text box (normal, side, additional, header, submit).
218 - * @param bool $ wrap Whether the content of the text box shall be wrapped in a <div> container.
231 + * @param bool $wrap Whether the content of the text box shall be wrapped in a <div> container.
219 232 */
220 - protected function add_text_box( $id, $callback, $context = 'normal', $wrap = false ) {
233 + protected function add_text_box( string $id, callable $callback, string $context = 'normal', bool $wrap = false ): void {
221 234 if ( ! isset( $this->textboxes[ $context ] ) ) {
222 235 $this->textboxes[ $context ] = array();
223 236 }
224 237
@@ -235,16 +248,16 @@
235 248 * Register a post meta box for the view, that is drag/droppable with WordPress functionality.
236 249 *
237 250 * @since 1.0.0
238 251 *
239 - * @param string $id Unique ID for the meta box.
240 - * @param string $title Title for the meta box.
241 - * @param callback $callback Callback that prints the contents of the post meta box.
242 - * @param string $context Optional. Context/position of the post meta box (normal, side, additional).
243 - * @param string $priority Optional. Order of the post meta box for the $context position (high, default, low).
244 - * @param bool $callback_args Optional. Additional data for the callback function (e.g. useful when in different class).
252 + * @param string $id Unique ID for the meta box.
253 + * @param string $title Title for the meta box.
254 + * @param callable $callback Callback that prints the contents of the post meta box.
255 + * @param 'normal'|'side'|'additional' $context Optional. Context/position of the post meta box (normal, side, additional).
256 + * @param 'core'|'default'|'high'|'low' $priority Optional. Order of the post meta box for the $context position (high, default, low).
257 + * @param mixed[]|null $callback_args Optional. Additional data for the callback function (e.g. useful when in different class).
245 258 */
246 - protected function add_meta_box( $id, $title, $callback, $context = 'normal', $priority = 'default', $callback_args = null ) {
259 + protected function add_meta_box( string $id, string $title, callable $callback, string $context = 'normal', string $priority = 'default', ?array $callback_args = null ): void {
247 260 $this->has_meta_boxes = true;
248 261 add_meta_box( "tablepress_{$this->action}-{$id}", $title, $callback, null, $context, $priority, $callback_args );
249 262 }
250 263
@@ -254,9 +267,9 @@
254 267 * @since 1.0.0
255 268 *
256 269 * @param string $context Context (normal, side, additional, header, submit) for which registered text boxes shall be rendered.
257 270 */
258 - protected function do_text_boxes( $context ) {
271 + protected function do_text_boxes( string $context ): void {
259 272 if ( empty( $this->textboxes[ $context ] ) ) {
260 273 return;
261 274 }
262 275
@@ -277,13 +290,12 @@
277 290 * @since 1.0.0
278 291 *
279 292 * @param string $context Context (normal, side, additional) for which registered post meta boxes shall be rendered.
280 293 */
281 - protected function do_meta_boxes( $context ) {
282 - if ( ! $this->has_meta_boxes ) {
283 - return;
294 + protected function do_meta_boxes( string $context ): void {
295 + if ( $this->has_meta_boxes ) {
296 + do_meta_boxes( get_current_screen(), $context, $this->data ); // @phpstan-ignore argument.type
284 297 }
285 - do_meta_boxes( null, $context, $this->data );
286 298 }
287 299
288 300 /**
289 301 * Print hidden fields with nonces for post meta box AJAX handling, if there are post meta boxes on the screen.
@@ -291,12 +303,12 @@
291 303 * The check is possible as this function is executed after post meta boxes have to be registered.
292 304 *
293 305 * @since 1.0.0
294 306 *
295 - * @param array $data Data for this screen.
296 - * @param array $box Information about the text box.
307 + * @param array<string, mixed> $data Data for this screen.
308 + * @param array<string, mixed> $box Information about the text box.
297 309 */
298 - protected function default_nonce_fields( array $data, array $box ) {
310 + protected function default_nonce_fields( array $data, array $box ): void {
299 311 if ( ! $this->has_meta_boxes ) {
300 312 return;
301 313 }
302 314 wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
@@ -309,12 +321,12 @@
309 321 * Print hidden field with a nonce for the screen's action, to be transmitted in HTTP requests.
310 322 *
311 323 * @since 1.0.0
312 324 *
313 - * @param array $data Data for this screen.
314 - * @param array $box Information about the text box.
325 + * @param array<string, mixed> $data Data for this screen.
326 + * @param array<string, mixed> $box Information about the text box.
315 327 */
316 - protected function action_nonce_field( array $data, array $box ) {
328 + protected function action_nonce_field( array $data, array $box ): void {
317 329 wp_nonce_field( TablePress::nonce( $this->action ) );
318 330 echo "\n";
319 331 }
320 332
@@ -322,13 +334,13 @@
322 334 * Print hidden field with the screen action.
323 335 *
324 336 * @since 1.0.0
325 337 *
326 - * @param array $data Data for this screen.
327 - * @param array $box Information about the text box.
338 + * @param array<string, mixed> $data Data for this screen.
339 + * @param array<string, mixed> $box Information about the text box.
328 340 */
329 - protected function action_field( array $data, array $box ) {
330 - echo "<input type=\"hidden\" name=\"action\" value=\"tablepress_{$this->action}\" />\n";
341 + protected function action_field( array $data, array $box ): void {
342 + echo "<input type=\"hidden\" name=\"action\" value=\"tablepress_{$this->action}\">\n";
331 343 }
332 344
333 345 /**
334 346 * Render the current view.
@@ -334,25 +346,30 @@
334 346 * Render the current view.
335 347 *
336 348 * @since 1.0.0
337 349 */
338 - public function render() {
350 + public function render(): void {
339 351 ?>
340 352 <div id="tablepress-page" class="wrap">
341 353 <?php
342 354 $this->print_nav_tab_menu();
343 - // Print all header messages.
344 - foreach ( $this->header_messages as $message ) {
345 - echo $message;
346 - }
347 - // "Import" screen has file upload.
348 - $enctype = ( 'import' === $this->action ) ? ' enctype="multipart/form-data"' : '';
349 355 ?>
350 - <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post"<?php echo $enctype; ?>>
356 + <div id="tablepress-body">
357 + <hr class="wp-header-end">
358 + <?php
359 + // Print all header messages.
360 + foreach ( $this->header_messages as $message ) {
361 + echo $message;
362 + }
363 + // "Import" screen has file upload.
364 + $enctype = ( 'import' === $this->action ) ? ' enctype="multipart/form-data"' : '';
365 + ?>
366 + <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post"<?php echo $enctype; ?> id="tablepress-page-form">
351 367 <?php
352 - $this->do_text_boxes( 'header' );
368 + $this->do_text_boxes( 'header' );
369 + $hide_if_no_js = ( in_array( $this->action, array( 'export', 'import' ), true ) ) ? ' class="hide-if-no-js"' : '';
353 370 ?>
354 - <div id="poststuff">
371 + <div id="poststuff"<?php echo $hide_if_no_js; ?>>
355 372 <div id="post-body" class="metabox-holder columns-<?php echo ( isset( $GLOBALS['screen_layout_columns'] ) && ( 2 === $GLOBALS['screen_layout_columns'] ) ) ? '2' : '1'; ?>">
356 373 <div id="postbox-container-2" class="postbox-container">
357 374 <?php
358 375 $this->do_text_boxes( 'normal' );
@@ -372,12 +389,13 @@
372 389 $this->do_meta_boxes( 'side' );
373 390 ?>
374 391 </div>
375 392 </div>
376 - <br class="clear" />
393 + <br class="clear">
377 394 </div>
378 395 </form>
379 396 </div>
397 + </div>
380 398 <?php
381 399 }
382 400
383 401 /**
@@ -384,12 +402,38 @@
384 402 * Render the navigation menu with links to the possible actions, highlighting the current one.
385 403 *
386 404 * @since 1.0.0
387 405 */
388 - protected function print_nav_tab_menu() {
406 + protected function print_nav_tab_menu(): void {
407 + $name = __( 'TablePress', 'tablepress' );
408 + $filename = 'admin/img/tablepress.svg';
389 409 ?>
390 - <div id="tablepress-nav" class="nav-tab-wrapper">
391 - <h1 class="wp-heading-inline"><?php _e( 'TablePress', 'tablepress' ); ?></h1>
410 + <div id="tablepress-header" class="header">
411 + <h1 class="name">
412 + <img src="<?php echo plugins_url( $filename, TABLEPRESS__FILE__ ); ?>" alt="<?php esc_attr_e( 'TablePress plugin logo', 'tablepress' ); ?>">
413 + <span class="screen-reader-text"><?php echo $name; ?></span>
414 + </h1>
415 + <?php if ( ! TABLEPRESS_IS_PLAYGROUND_PREVIEW && tb_tp_fs()->is_free_plan() ) : ?>
416 + <div class="buttons">
417 + <?php
418 + $timestamp_today = strtotime( 'today' );
419 + if ( strtotime( '2024-11-24' ) < $timestamp_today && $timestamp_today < strtotime( '2024-12-03' ) ) :
420 + ?>
421 + <a href="https://tablepress.org/premium/?utm_campaign=black-week-2024&utm_source=plugin&utm_medium=button&utm_content=upgrade-button" class="tablepress-button" style="background:linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);border-color:#ffffff;font-weight:bold;font-size:20px;border-radius:6px;">
422 + <span>Premium: 20% off during Black Week 2024!</span>
423 + <span class="dashicons dashicons-arrow-right-alt" />
424 + </a>
425 + <?php else : ?>
426 + <a href="<?php echo esc_url( tb_tp_fs()->pricing_url( WP_FS__PERIOD_ANNUALLY, false ) ); ?>" class="tablepress-button">
427 + <span><?php _e( 'Upgrade to Premium', 'tablepress' ); ?></span>
428 + <span class="dashicons dashicons-arrow-right-alt"></span>
429 + </a>
430 + <?php endif; ?>
431 + </div>
432 + <?php endif; ?>
433 + </div>
434 + <nav id="tablepress-nav">
435 + <ul class="nav-menu">
392 436 <?php
393 437 foreach ( $this->data['view_actions'] as $action => $entry ) {
394 438 if ( '' === $entry['nav_tab_title'] ) {
395 439 continue;
@@ -398,29 +442,56 @@
398 442 continue;
399 443 }
400 444
401 445 $url = esc_url( TablePress::url( array( 'action' => $action ) ) );
402 - $active = ( $action === $this->action ) ? ' nav-tab-active' : '';
403 - $separator = ( 'options' === $action ) ? ' nav-tab-separator' : ''; // Make the "Plugin Options" entry a separator, for some spacing.
404 - echo "<a class=\"nav-tab{$active}{$separator}\" href=\"{$url}\">{$entry['nav_tab_title']}</a>";
446 + $active = ( $action === $this->action ) ? ' active' : '';
447 + $separator = ( 'export' === $action ) ? ' separator' : ''; // Make the "Export" entry a separator, for some spacing.
448 + echo "<li class=\"nav-item\"><a id=\"tablepress-nav-item-{$action}\" class=\"nav-link{$active}{$separator}\" href=\"{$url}\">{$entry['nav_tab_title']}</a></li>";
405 449 }
406 450 ?>
407 - </div><hr class="wp-header-end" />
451 + </ul>
452 + </nav>
408 453 <?php
409 454 }
410 455
411 456 /**
412 - * Print a submit button (only done when function is used as a callback for a text box).
457 + * Prints a notification about JavaScript not being activated in the browser.
413 458 *
459 + * @since 2.0.0
460 + *
461 + * @param array<string, mixed> $data Data for this screen.
462 + * @param array<string, mixed> $box Information about the text box.
463 + */
464 + public function textbox_no_javascript( array $data, array $box ): void {
465 + ?>
466 + <div class="notice notice-error notice-alt notice-large hide-if-js">
467 + <h3><em>
468 + <?php _e( 'Attention: Unfortunately, there is a problem!', 'tablepress' ); ?>
469 + </em></h3>
470 + <p style="font-size:14px">
471 + <strong><?php _e( 'This screen requires JavaScript. Please enable JavaScript in your browser settings.', 'tablepress' ); ?></strong><br>
472 + <?php _e( 'For help, please follow <a href="https://www.enable-javascript.com/">the instructions on how to enable JavaScript in your browser</a>.', 'tablepress' ); ?>
473 + </p>
474 + <p>
475 + <?php echo '<a href="' . esc_url( TablePress::url( array( 'action' => 'list' ) ) ) . '">' . __( 'Back to the List of Tables', 'tablepress' ) . '</a>'; ?>
476 + </p>
477 + </div>
478 + <?php
479 + }
480 +
481 + /**
482 + * Prints a submit button (only done when function is used as a callback for a text box).
483 + *
484 + * This method is soft-deprecated. It's no longer used in TablePress, but e.g. in the "TablePress Debug Extension".
485 + *
414 486 * @since 1.0.0
415 487 *
416 - * @param array $data Data for this screen.
417 - * @param array $box Information about the text box.
488 + * @param array<string, mixed> $data Data for this screen.
489 + * @param array<string, mixed> $box Information about the text box.
418 490 */
419 - protected function textbox_submit_button( array $data, array $box ) {
420 - $caption = isset( $data['submit_button_caption'] ) ? $data['submit_button_caption'] : __( 'Save Changes', 'tablepress' );
491 + protected function textbox_submit_button( array $data, array $box ): void {
421 492 ?>
422 - <p class="submit"><input type="submit" value="<?php echo esc_attr( $caption ); ?>" class="button button-primary button-large" name="submit" /></p>
493 + <p class="submit"><input type="submit" class="components-button is-primary button-save-changes" value="<?php esc_attr_e( 'Save Changes', 'tablepress' ); ?>"></p>
423 494 <?php
424 495 }
425 496
426 497 /**
@@ -428,10 +499,12 @@
428 499 *
429 500 * Has to be implemented for every view that is visible in the WP Dashboard!
430 501 *
431 502 * @since 1.0.0
503 + *
504 + * @return string Help tab content for the view.
432 505 */
433 - protected function help_tab_content() {
506 + protected function help_tab_content(): string {
434 507 // Has to be implemented for every view that is visible in the WP Dashboard!
435 508 return '';
436 509 }
437 510
@@ -439,9 +512,9 @@
439 512 * Initialize the WP feature pointers for TablePress.
440 513 *
441 514 * @since 1.0.0
442 515 */
443 - protected function _init_wp_pointers() {
516 + protected function _init_wp_pointers(): void {
444 517 // Check if there are WP pointers for this view.
445 518 if ( empty( $this->wp_pointers ) ) {
446 519 return;
447 520 }
@@ -448,21 +521,18 @@
448 521
449 522 // Get dismissed pointers.
450 523 $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
451 524
452 - $got_pointers = false;
525 + $pointers_on_page = false;
453 526 foreach ( array_diff( $this->wp_pointers, $dismissed ) as $pointer ) {
454 527 // Bind pointer print function.
455 - add_action( "admin_footer-{$GLOBALS['hook_suffix']}", array( $this, 'wp_pointer_' . $pointer ) );
456 - $got_pointers = true;
528 + add_action( "admin_footer-{$GLOBALS['hook_suffix']}", array( $this, 'wp_pointer_' . $pointer ) ); // @phpstan-ignore argument.type
529 + $pointers_on_page = true;
457 530 }
458 531
459 - if ( ! $got_pointers ) {
460 - return;
532 + if ( $pointers_on_page ) {
533 + wp_enqueue_style( 'wp-pointer' );
534 + wp_enqueue_script( 'wp-pointer' );
461 535 }
462 -
463 - // Add pointers script and style to queue.
464 - wp_enqueue_style( 'wp-pointer' );
465 - wp_enqueue_script( 'wp-pointer' );
466 536 }
467 537
468 538 } // class TablePress_View