*/ protected $data = array(); /** * Number of screen columns for post boxes. * * @since 1.0.0 * @var int */ protected $screen_columns = 0; /** * User action for this screen. * * @since 1.0.0 * @var string */ protected $action = ''; /** * Instance of the Admin Page Helper Class, with necessary functions. * * @since 1.0.0 * @var TablePress_Admin_Page */ protected $admin_page; /** * List of text boxes (similar to post boxes, but just with text and without extra functionality). * * @since 1.0.0 * @var array>> */ protected $textboxes = array(); /** * List of messages that are to be displayed as boxes below the page title. * * @since 1.0.0 * @var string[] */ protected $header_messages = array(); /** * Whether there are post boxes registered for this screen, * is automatically set to true, when a meta box is added. * * @since 1.0.0 * @var bool */ protected $has_meta_boxes = false; /** * List of WP feature pointers for this view. * * @since 1.0.0 * @var string[] */ protected $wp_pointers = array(); /** * Initialize the View class, by setting the correct screen columns and adding help texts. * * @since 1.0.0 */ public function __construct() { $screen = get_current_screen(); if ( 0 !== $this->screen_columns ) { $screen->add_option( 'layout_columns', array( 'max' => $this->screen_columns ) ); } // Enable two column layout. add_filter( "get_user_option_screen_layout_{$screen->id}", array( $this, 'set_current_screen_layout_columns' ) ); $common_content = '

' . sprintf( __( 'More information about TablePress can be found on the plugin website or on its page in the WordPress Plugin Directory.', 'tablepress' ), 'https://tablepress.org/', 'https://wordpress.org/plugins/tablepress/' ) . '

'; $common_content .= '

' . sprintf( __( 'For technical information, please see the Documentation.', 'tablepress' ), 'https://tablepress.org/documentation/' ) . ' ' . sprintf( __( 'Common questions are answered in the FAQ.', 'tablepress' ), 'https://tablepress.org/faq/' ) . '

'; if ( tb_tp_fs()->is_free_plan() ) { $common_content .= '

' . sprintf( __( 'Support is provided through the WordPress Support Forums.', 'tablepress' ), 'https://tablepress.org/support/', 'https://wordpress.org/tags/tablepress' ) . ' ' . sprintf( __( 'Before asking for support, please carefully read the Frequently Asked Questions, where you will find answers to the most common questions, and search through the forums.', 'tablepress' ), 'https://tablepress.org/faq/' ) . '

'; $common_content .= '

' . sprintf( __( 'More great features for you and your site’s visitors and priority email support are available with a Premium license plan of TablePress. Go check them out!', 'tablepress' ), 'https://tablepress.org/premium/?utm_source=plugin&utm_medium=textlink&utm_content=help-tab' ) . '

'; } $screen->add_help_tab( array( 'id' => 'tablepress-help', // This should be unique for the screen. 'title' => __( 'TablePress Help', 'tablepress' ), 'content' => '

' . $this->help_tab_content() . '

' . $common_content, ) ); // "Sidebar" in the help tab. $screen->set_help_sidebar( '

' . __( 'For more information:', 'tablepress' ) . '

' . '

TablePress Website

' . '

TablePress FAQ

' . '

TablePress Documentation

' . '

TablePress Support

' ); } /** * Change the value of the user option "screen_layout_{$screen->id}" through a filter. * * @since 1.0.0 * * @param int|false $result Current value of the user option. * @return int New value for the user option. */ public function set_current_screen_layout_columns( /* int|false */ $result ): int { if ( false === $result ) { // The user option does not yet exist. $result = $this->screen_columns; } elseif ( $result > $this->screen_columns ) { // The value of the user option is bigger than what is possible on this screen (e.g. because the number of columns was reduced in an update). $result = $this->screen_columns; } return $result; } /** * Set up the view with data and do things that are necessary for all views. * * @since 1.0.0 * * @param string $action Action for this view. * @param array $data Data for this view. */ public function setup( /* string */ $action, array $data ) /* : void */ { // 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. $this->action = $action; $this->data = $data; // Set page title. $GLOBALS['title'] = sprintf( __( '%1$s ‹ %2$s', 'tablepress' ), $this->data['view_actions'][ $this->action ]['page_title'], 'TablePress' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited // Admin page helpers, like script/style loading, could be moved to view. $this->admin_page = TablePress::load_class( 'TablePress_Admin_Page', 'class-admin-page-helper.php', 'classes' ); $this->admin_page->enqueue_style( 'common' ); // RTL styles for the admin interface. if ( is_rtl() ) { $this->admin_page->enqueue_style( 'common-rtl', array( 'tablepress-common' ) ); } $this->admin_page->enqueue_script( 'common', array( 'jquery-core', 'postbox' ) ); $this->admin_page->add_admin_footer_text(); // Initialize WP feature pointers for TablePress. $this->_init_wp_pointers(); // Necessary fields for all views. $this->add_text_box( 'default_nonce_fields', array( $this, 'default_nonce_fields' ), 'header', false ); $this->add_text_box( 'action_nonce_field', array( $this, 'action_nonce_field' ), 'header', false ); $this->add_text_box( 'action_field', array( $this, 'action_field' ), 'header', false ); } /** * Register a header message for the view. * * @since 1.0.0 * * @param string $text Text for the header message. * @param string $css_class Optional. Additional CSS class for the header message. * @param string $title Optional. Text for the header title. */ protected function add_header_message( string $text, string $css_class = 'notice-success', string $title = '' ): void { if ( ! str_contains( $css_class, 'not-dismissible' ) ) { $css_class .= ' is-dismissible'; } if ( '' !== $title ) { $title = "

{$title}

"; } // Wrap the message text in HTML

tags if it does not already start with one (potentially with attributes), indicating custom message HTML. if ( '' !== $text && ! str_starts_with( $text, 'header_messages[] = "

{$title}{$text}
\n"; } /** * Process header action messages, i.e. check if a message should be added to the page. * * @since 1.0.0 * * @param array $action_messages Action messages for the screen. */ protected function process_action_messages( array $action_messages ): void { if ( $this->data['message'] && isset( $action_messages[ $this->data['message'] ] ) ) { $class = ( str_starts_with( $this->data['message'], 'error' ) ) ? 'notice-error' : 'notice-success'; if ( '' !== $this->data['error_details'] ) { $this->data['error_details'] = '

' . sprintf( __( 'Error code: %s', 'tablepress' ), '' . esc_html( $this->data['error_details'] ) . '' ); } $this->add_header_message( "{$action_messages[ $this->data['message'] ]}{$this->data['error_details']}", $class ); } } /** * Register a text box for the view. * * @since 1.0.0 * * @param string $id Unique HTML ID for the text box container (only visible with $wrap = true). * @param callable $callback Callback that prints the contents of the text box. * @param string $context Optional. Context/position of the text box (normal, side, additional, header, submit). * @param bool $wrap Whether the content of the text box shall be wrapped in a

container. */ protected function add_text_box( string $id, callable $callback, string $context = 'normal', bool $wrap = false ): void { if ( ! isset( $this->textboxes[ $context ] ) ) { $this->textboxes[ $context ] = array(); } $long_id = "tablepress_{$this->action}-{$id}"; $this->textboxes[ $context ][ $id ] = array( 'id' => $long_id, 'callback' => $callback, 'context' => $context, 'wrap' => $wrap, ); } /** * Register a post meta box for the view, that is drag/droppable with WordPress functionality. * * @since 1.0.0 * * @param string $id Unique ID for the meta box. * @param string $title Title for the meta box. * @param callable $callback Callback that prints the contents of the post meta box. * @param 'normal'|'side'|'additional' $context Optional. Context/position of the post meta box (normal, side, additional). * @param 'core'|'default'|'high'|'low' $priority Optional. Order of the post meta box for the $context position (high, default, low). * @param mixed[]|null $callback_args Optional. Additional data for the callback function (e.g. useful when in different class). */ protected function add_meta_box( string $id, string $title, callable $callback, string $context = 'normal', string $priority = 'default', ?array $callback_args = null ): void { $this->has_meta_boxes = true; add_meta_box( "tablepress_{$this->action}-{$id}", $title, $callback, null, $context, $priority, $callback_args ); } /** * Render all text boxes for the given context. * * @since 1.0.0 * * @param string $context Context (normal, side, additional, header, submit) for which registered text boxes shall be rendered. */ protected function do_text_boxes( string $context ): void { if ( empty( $this->textboxes[ $context ] ) ) { return; } foreach ( $this->textboxes[ $context ] as $box ) { if ( $box['wrap'] ) { echo "
\n"; } call_user_func( $box['callback'], $this->data, $box ); if ( $box['wrap'] ) { echo "
\n"; } } } /** * Render all post meta boxes for the given context, if there are post meta boxes. * * @since 1.0.0 * * @param string $context Context (normal, side, additional) for which registered post meta boxes shall be rendered. */ protected function do_meta_boxes( string $context ): void { if ( $this->has_meta_boxes ) { do_meta_boxes( get_current_screen(), $context, $this->data ); // @phpstan-ignore-line } } /** * Print hidden fields with nonces for post meta box AJAX handling, if there are post meta boxes on the screen. * * The check is possible as this function is executed after post meta boxes have to be registered. * * @since 1.0.0 * * @param array $data Data for this screen. * @param array $box Information about the text box. */ protected function default_nonce_fields( array $data, array $box ): void { if ( ! $this->has_meta_boxes ) { return; } wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); echo "\n"; wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); echo "\n"; } /** * Print hidden field with a nonce for the screen's action, to be transmitted in HTTP requests. * * @since 1.0.0 * * @param array $data Data for this screen. * @param array $box Information about the text box. */ protected function action_nonce_field( array $data, array $box ): void { wp_nonce_field( TablePress::nonce( $this->action ) ); echo "\n"; } /** * Print hidden field with the screen action. * * @since 1.0.0 * * @param array $data Data for this screen. * @param array $box Information about the text box. */ protected function action_field( array $data, array $box ): void { echo "action}\" />\n"; } /** * Render the current view. * * @since 1.0.0 */ public function render(): void { ?>
print_nav_tab_menu(); ?>

header_messages as $message ) { echo $message; } // "Import" screen has file upload. $enctype = ( 'import' === $this->action ) ? ' enctype="multipart/form-data"' : ''; ?>
> do_text_boxes( 'header' ); $hide_if_no_js = ( in_array( $this->action, array( 'export', 'import' ), true ) ) ? ' class="hide-if-no-js"' : ''; ?>
>
do_text_boxes( 'normal' ); $this->do_meta_boxes( 'normal' ); $this->do_text_boxes( 'additional' ); $this->do_meta_boxes( 'additional' ); // Print all submit buttons. $this->do_text_boxes( 'submit' ); ?>
do_text_boxes( 'side' ); $this->do_meta_boxes( 'side' ); ?>

<?php esc_attr_e( 'TablePress plugin logo', 'tablepress' ); ?>

is_free_plan() ) : ?>
$data Data for this screen. * @param array $box Information about the text box. */ public function textbox_no_javascript( array $data, array $box ): void { ?>


the instructions on how to enable JavaScript in your browser.', 'tablepress' ); ?>

'list' ) ) . '">' . __( 'Back to the List of Tables', 'tablepress' ) . ''; ?>

$data Data for this screen. * @param array $box Information about the text box. */ protected function textbox_submit_button( array $data, array $box ): void { $caption = $data['submit_button_caption'] ?? __( 'Save Changes', 'tablepress' ); ?>

wp_pointers ) ) { return; } // Get dismissed pointers. $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); $pointers_on_page = false; foreach ( array_diff( $this->wp_pointers, $dismissed ) as $pointer ) { // Bind pointer print function. add_action( "admin_footer-{$GLOBALS['hook_suffix']}", array( $this, 'wp_pointer_' . $pointer ) ); // @phpstan-ignore-line $pointers_on_page = true; } if ( $pointers_on_page ) { wp_enqueue_style( 'wp-pointer' ); wp_enqueue_script( 'wp-pointer' ); } } } // class TablePress_View