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 | controllers/controller-admin.php +51 -42 2.4.13.0 View file →
@@ -27,9 +27,9 @@
27 27 *
28 28 * @since 1.0.0
29 29 * @var string[]
30 30 */
31 - protected $page_hooks = array();
31 + protected array $page_hooks = array();
32 32
33 33 /**
34 34 * Actions that have a view and admin menu or nav tab menu entry.
35 35 *
@@ -35,17 +35,16 @@
35 35 *
36 36 * @since 1.0.0
37 37 * @var array<string, array<string, bool|string>>
38 38 */
39 - protected $view_actions = array();
39 + protected array $view_actions = array();
40 40
41 41 /**
42 42 * Instance of the TablePress Admin View that is rendered.
43 43 *
44 44 * @since 1.0.0
45 - * @var TablePress_View
46 45 */
47 - protected $view;
46 + protected \TablePress_View $view;
48 47
49 48 /**
50 49 * Initialize the Admin Controller, determine location the admin menu, set up actions.
51 50 *
@@ -97,11 +96,11 @@
97 96
98 97 $this->init_view_actions();
99 98 $min_access_cap = $this->view_actions['list']['required_cap'];
100 99
101 - if ( $this->is_top_level_page ) {
102 - $icon_url = 'dashicons-list-view';
103 - switch ( $this->parent_page ) {
100 + if ( TablePress::$controller->is_top_level_page ) {
101 + $icon_url = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iLTMyIC0zMiA2NCA2NCIgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTAtMjUuODU0aC0yNS44NTR2NTEuNzA4aDUxLjcwOFYwSDIxdjIxaC00MnYtNDJIMFoiLz48cGF0aCBkPSJNLTE4LTE4aDEwdjEwaC0xMHpNLTE4LTVoMTBWNWgtMTB6TS01LTVINVY1SC01ek0tMTggOGgxMHYxMGgtMTB6TS01IDhINXYxMEgtNXpNOCA4aDEwdjEwSDh6TTUtMzFoNi4xOHY2LjE4SDV6TTE5LTI1aDYuMTh2Ni4xOEgxOXpNMC0xNWgzLjgydjMuODJIMHpNMTAtMjBoMy44MnYzLjgySDEwek0yNS0xMmgzLjgydjMuODJIMjV6TTgtMTNoMTB2MTBIOHoiLz48L3N2Zz4=';
102 + switch ( TablePress::$controller->parent_page ) {
104 103 case 'top':
105 104 $position = 3; // Position of Dashboard + 1.
106 105 break;
107 106 case 'bottom':
@@ -115,9 +114,9 @@
115 114 // Prevent overwriting existing menu entries.
116 115 while ( isset( $GLOBALS['menu'][ $position ] ) ) {
117 116 ++$position;
118 117 }
119 - add_menu_page( 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback, $icon_url, $position ); // @phpstan-ignore-line
118 + add_menu_page( 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback, $icon_url, $position ); // @phpstan-ignore argument.type
120 119 foreach ( $this->view_actions as $action => $entry ) {
121 120 if ( ! $entry['show_entry'] ) {
122 121 continue;
123 122 }
@@ -124,9 +123,9 @@
124 123 $slug = 'tablepress';
125 124 if ( 'list' !== $action ) {
126 125 $slug .= '_' . $action;
127 126 }
128 - // @phpstan-ignore-next-line
127 + // @phpstan-ignore argument.type, argument.type
129 128 $page_hook = add_submenu_page( 'tablepress', sprintf( __( '%1$s &lsaquo; %2$s', 'tablepress' ), $entry['page_title'], 'TablePress' ), $entry['admin_menu_title'], $entry['required_cap'], $slug, $callback );
130 129 if ( false !== $page_hook ) {
131 130 $this->page_hooks[] = $page_hook;
132 131 }
@@ -131,10 +130,10 @@
131 130 $this->page_hooks[] = $page_hook;
132 131 }
133 132 }
134 133 } else {
135 - // @phpstan-ignore-next-line
136 - $page_hook = add_submenu_page( $this->parent_page, 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback );
134 + // @phpstan-ignore argument.type
135 + $page_hook = add_submenu_page( TablePress::$controller->parent_page, 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback );
137 136 if ( false !== $page_hook ) {
138 137 $this->page_hooks[] = $page_hook;
139 138 }
140 139 }
@@ -179,13 +178,8 @@
179 178 add_action( 'admin_bar_menu', array( $this, 'add_wp_admin_bar_new_content_menu_entry' ), 71 );
180 179 }
181 180
182 181 add_action( 'load-plugins.php', array( $this, 'plugins_page' ) );
183 -
184 - // Add filters and actions for the integration into the WP WXR exporter and importer.
185 - add_action( 'wp_import_insert_post', array( TablePress::$model_table, 'add_table_id_on_wp_import' ), 10, 4 );
186 - add_filter( 'wp_import_post_meta', array( TablePress::$model_table, 'prevent_table_id_post_meta_import_on_wp_import' ), 10, 3 );
187 - add_filter( 'wxr_export_skip_postmeta', array( TablePress::$model_table, 'add_table_id_to_wp_export' ), 10, 3 );
188 182 }
189 183
190 184 /**
191 185 * Loads additional JavaScript code for the TablePress table block (in the block editor context).
@@ -192,8 +186,16 @@
192 186 *
193 187 * @since 2.2.0
194 188 */
195 189 public function enqueue_block_editor_assets(): void {
190 + /*
191 + * Register the `react-jsx-runtime` polyfill, if it is not already registered.
192 + * This is needed as a polyfill for WP < 6.6, and can be removed once WP 6.6 is the minimum requirement for TablePress.
193 + */
194 + if ( ! wp_script_is( 'react-jsx-runtime', 'registered' ) ) {
195 + wp_register_script( 'react-jsx-runtime', plugins_url( 'admin/js/react-jsx-runtime.min.js', TABLEPRESS__FILE__ ), array( 'react' ), TablePress::version, true );
196 + }
197 +
196 198 // Add table information for the block editor to the page.
197 199 $handle = generate_block_asset_handle( 'tablepress/table', 'editorScript' );
198 200 $data = $this->get_block_editor_data();
199 201 wp_add_inline_script( $handle, $data, 'before' );
@@ -280,17 +282,17 @@
280 282 $url = TablePress::url( array( 'action' => 'list' ) );
281 283 }
282 284
283 285 return <<<JS
284 -// Ensure the global `tp` object exists.
285 -window.tp = window.tp || {};
286 -tp.url = '{$url}';
287 -tp.load_block_preview = {$load_block_preview};
288 -tp.table = {};
289 -tp.table.shortcode = '{$shortcode}';
290 -tp.table.template = JSON.parse( '{$template}' );
291 -tp.tables = JSON.parse( '{$tables}' );
292 -JS;
286 + // Ensure the global `tp` object exists.
287 + window.tp = window.tp || {};
288 + tp.url = '{$url}';
289 + tp.load_block_preview = {$load_block_preview};
290 + tp.table = {};
291 + tp.table.shortcode = '{$shortcode}';
292 + tp.table.template = JSON.parse( '{$template}' );
293 + tp.tables = JSON.parse( '{$tables}' );
294 + JS;
293 295 }
294 296
295 297 /**
296 298 * Register actions to add "Table" button to "HTML editor" and "Visual editor" toolbars.
@@ -318,9 +320,9 @@
318 320 'title' => __( 'Insert a TablePress table', 'tablepress' ),
319 321 'thickbox_title' => __( 'Insert a TablePress table', 'tablepress' ),
320 322 'thickbox_url' => TablePress::url( array( 'action' => 'editor_button_thickbox' ), true, 'admin-post.php' ),
321 323 ),
322 - )
324 + ),
323 325 );
324 326
325 327 // TinyMCE integration.
326 328 if ( user_can_richedit() ) {
@@ -460,9 +462,9 @@
460 462 if ( tb_tp_fs()->is_free_plan() ) {
461 463 echo '<p style="font-size:14px;">';
462 464 _e( 'This TablePress Extension was retired.', 'tablepress' );
463 465 echo ' ';
464 - _e( '<strong>The plugin will stop working with TablePress 3 later this year</strong> and will no longer receive updates or support!', 'tablepress' );
466 + _e( '<strong>The plugin does no longer work with TablePress 3</strong> and will no longer receive updates or support!', 'tablepress' );
465 467 echo '<br>';
466 468 _e( 'Keeping it activated can lead to errors on your website!', 'tablepress' );
467 469 echo ' <strong>' . sprintf( __( '<a href="%s">Find out what you can do to continue using its features!</a>', 'tablepress' ), 'https://tablepress.org/upgrade-extensions/?utm_source=plugin&utm_medium=textlink&utm_content=plugins-list-table' ) . '</strong>';
468 470 echo '</p>';
@@ -492,9 +494,9 @@
492 494 */
493 495 public function load_admin_page(): void {
494 496 // Determine the action from either the GET parameter (for sub-menu entries, and the main admin menu entry).
495 497 $action = ( ! empty( $_GET['action'] ) ) ? $_GET['action'] : 'list'; // Default action is list.
496 - if ( $this->is_top_level_page ) {
498 + if ( TablePress::$controller->is_top_level_page ) {
497 499 // Or, for sub-menu entry of an admin menu "TablePress" entry, get it from the "page" GET parameter.
498 500 if ( 'tablepress' !== $_GET['page'] ) {
499 501 // Actions that are top-level entries, but don't have an action GET parameter (action is after last _ in string).
500 502 $action = substr( $_GET['page'], 11 ); // $_GET['page'] has the format 'tablepress_{$action}'
@@ -501,9 +503,9 @@
501 503 }
502 504 }
503 505
504 506 // Check if action is a supported action, and whether the user is allowed to access this screen.
505 - if ( ! isset( $this->view_actions[ $action ] ) || ! current_user_can( $this->view_actions[ $action ]['required_cap'] ) ) { // @phpstan-ignore-line (The array value for the capability is always a string.)
507 + if ( ! isset( $this->view_actions[ $action ] ) || ! current_user_can( $this->view_actions[ $action ]['required_cap'] ) ) { // @phpstan-ignore argument.type (The array value for the capability is always a string.)
506 508 wp_die( __( 'Sorry, you are not allowed to access this page.', 'default' ), 403 );
507 509 }
508 510
509 511 // Don't load TablePress assets on the Freemius opt-in/activation screen.
@@ -538,9 +540,9 @@
538 540 $data['table_ids'] = TablePress::$model_table->load_all( true );
539 541 $data['messages']['donation_nag'] = $this->maybe_show_donation_message();
540 542 $data['messages']['first_visit'] = ! $data['messages']['donation_nag'] && TablePress::$model_options->get( 'message_first_visit' );
541 543 $data['messages']['plugin_update'] = TablePress::$model_options->get( 'message_plugin_update' );
542 - $data['messages']['superseded_extensions'] = TablePress::$model_options->get( 'message_superseded_extensions' );
544 + $data['messages']['superseded_extensions'] = current_user_can( 'manage_options' ) && TablePress::$model_options->get( 'message_superseded_extensions' );
543 545 $data['table_count'] = count( $data['table_ids'] );
544 546 break;
545 547 case 'about':
546 548 $data['first_activation'] = TablePress::$model_options->get( 'first_activation' );
@@ -551,9 +553,9 @@
551 553 * (called here, as the credentials form posts to this handler again, due to how `request_filesystem_credentials()` works)
552 554 */
553 555 if ( isset( $_GET['item'] ) && 'save_custom_css' === $_GET['item'] ) {
554 556 TablePress::check_nonce( 'options', $_GET['item'] ); // Nonce check here, as we don't have an explicit handler, and even viewing the screen needs to be checked.
555 - $action = 'options_custom_css'; // to load a different view
557 + $action = 'options_custom_css'; // To load a different view.
556 558 // Try saving "Custom CSS" to a file, otherwise this gets the HTML for the credentials form.
557 559 $tablepress_css = TablePress::load_class( 'TablePress_CSS', 'class-css.php', 'classes' );
558 560 $result = $tablepress_css->save_custom_css_to_file_plugin_options( TablePress::$model_options->get( 'custom_css' ), TablePress::$model_options->get( 'custom_css_minified' ) );
559 561 if ( is_string( $result ) ) {
@@ -574,9 +576,9 @@
574 576 break;
575 577 }
576 578 $data['frontend_options']['use_custom_css'] = TablePress::$model_options->get( 'use_custom_css' );
577 579 $data['frontend_options']['custom_css'] = TablePress::$model_options->get( 'custom_css' );
578 - $data['user_options']['parent_page'] = $this->parent_page;
580 + $data['user_options']['parent_page'] = TablePress::$controller->parent_page;
579 581 break;
580 582 case 'edit':
581 583 if ( empty( $_GET['table_id'] ) ) {
582 584 TablePress::redirect( array( 'action' => 'list', 'message' => 'error_no_table' ) );
@@ -868,10 +870,10 @@
868 870
869 871 $add_table = wp_unslash( $_POST['table'] );
870 872
871 873 // Perform confidence checks of posted data.
872 - $name = ( isset( $add_table['name'] ) ) ? $add_table['name'] : '';
873 - $description = ( isset( $add_table['description'] ) ) ? $add_table['description'] : '';
874 + $name = $add_table['name'] ?? '';
875 + $description = $add_table['description'] ?? '';
874 876 if ( ! isset( $add_table['rows'], $add_table['columns'] ) ) {
875 877 TablePress::redirect( array( 'action' => 'add', 'message' => 'error_add', 'error_details' => 'The HTTP POST data does not contain the table size.' ) );
876 878 }
877 879
@@ -931,10 +933,10 @@
931 933 if ( ! empty( $posted_options['admin_menu_parent_page'] ) && '-' !== $posted_options['admin_menu_parent_page'] ) {
932 934 $new_options['admin_menu_parent_page'] = $posted_options['admin_menu_parent_page'];
933 935 // Re-init parent information, as `TablePress::redirect()` URL might be wrong otherwise.
934 936 /** This filter is documented in classes/class-controller.php */
935 - $this->parent_page = apply_filters( 'tablepress_admin_menu_parent_page', $posted_options['admin_menu_parent_page'] );
936 - $this->is_top_level_page = in_array( $this->parent_page, array( 'top', 'middle', 'bottom' ), true );
937 + TablePress::$controller->parent_page = apply_filters( 'tablepress_admin_menu_parent_page', $posted_options['admin_menu_parent_page'] );
938 + TablePress::$controller->is_top_level_page = in_array( TablePress::$controller->parent_page, array( 'top', 'middle', 'bottom' ), true );
937 939 }
938 940
939 941 // Custom CSS can only be saved if the user is allowed to do so.
940 942 $update_custom_css_files = false;
@@ -945,13 +947,20 @@
945 947 if ( isset( $posted_options['custom_css'] ) ) {
946 948 $new_options['custom_css'] = $posted_options['custom_css'];
947 949
948 950 $tablepress_css = TablePress::load_class( 'TablePress_CSS', 'class-css.php', 'classes' );
949 - // Sanitize and tidy up Custom CSS.
950 - $new_options['custom_css'] = $tablepress_css->sanitize_css( $new_options['custom_css'] );
951 - // Minify Custom CSS.
952 - $new_options['custom_css_minified'] = $tablepress_css->minify_css( $new_options['custom_css'] );
953 951
952 + if ( '' !== $new_options['custom_css'] ) {
953 + // Update "Custom CSS" to use DataTables 2 variants instead of old DataTables 1.x CSS classes.
954 + $new_options['custom_css'] = TablePress::convert_datatables_api_data( $new_options['custom_css'] );
955 + // Sanitize and tidy up Custom CSS.
956 + $new_options['custom_css'] = $tablepress_css->sanitize_css( $new_options['custom_css'] );
957 + // Minify Custom CSS.
958 + $new_options['custom_css_minified'] = $tablepress_css->minify_css( $new_options['custom_css'] );
959 + } else {
960 + $new_options['custom_css_minified'] = '';
961 + }
962 +
954 963 // Maybe update CSS files as well.
955 964 $custom_css_file_contents = $tablepress_css->load_custom_css_from_file( 'normal' );
956 965 if ( false === $custom_css_file_contents ) {
957 966 $custom_css_file_contents = '';
@@ -1078,9 +1087,9 @@
1078 1087 /** This filter is documented in controllers/controller-admin.php */
1079 1088 $download_filename = apply_filters( 'tablepress_export_filename', $download_filename, '', '', $export['format'], $export_to_zip );
1080 1089 $download_filename = sanitize_file_name( $download_filename );
1081 1090 $full_filename = wp_tempnam( $download_filename );
1082 - if ( true !== $zip_file->open( $full_filename, ZIPARCHIVE::OVERWRITE ) ) {
1091 + if ( true !== $zip_file->open( $full_filename, ZipArchive::OVERWRITE ) ) {
1083 1092 @unlink( $full_filename ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1084 1093 TablePress::redirect( array( 'action' => 'export', 'message' => 'error_create_zip_file', 'export_format' => $export['format'], 'csv_delimiter' => $export['csv_delimiter'], 'error_details' => 'The ZIP file could not be opened for writing.' ) );
1085 1094 }
1086 1095
@@ -1110,9 +1119,9 @@
1110 1119 }
1111 1120
1112 1121 // If something went wrong, or no files were added to the ZIP file, bail out.
1113 1122 // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
1114 - if ( ZIPARCHIVE::ER_OK !== $zip_file->status || 0 === $zip_file->numFiles ) {
1123 + if ( ZipArchive::ER_OK !== $zip_file->status || 0 === $zip_file->numFiles ) {
1115 1124 $zip_file->close();
1116 1125 @unlink( $full_filename ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1117 1126 TablePress::redirect( array( 'action' => 'export', 'message' => 'error_create_zip_file', 'export_format' => $export['format'], 'csv_delimiter' => $export['csv_delimiter'], 'error_details' => 'The ZIP file could not be written or is empty.' ) );
1118 1127 }