PluginProbe
TablePress – Tables in WordPress made easy / 3.2
TablePress – Tables in WordPress made easy v3.2
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 +139 -65 2.3.23.2 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,23 +96,27 @@
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':
108 - $position = ( ++$GLOBALS['_wp_last_utility_menu'] );
107 + $position = isset( $GLOBALS['_wp_last_utility_menu'] ) ? ++$GLOBALS['_wp_last_utility_menu'] : 80;
109 108 break;
110 109 case 'middle':
111 110 default:
112 - $position = ( ++$GLOBALS['_wp_last_object_menu'] );
111 + $position = isset( $GLOBALS['_wp_last_object_menu'] ) ? ++$GLOBALS['_wp_last_object_menu'] : 25;
113 112 break;
114 113 }
115 - add_menu_page( 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback, $icon_url, $position ); // @phpstan-ignore-line
114 + // Prevent overwriting existing menu entries.
115 + while ( isset( $GLOBALS['menu'][ $position ] ) ) {
116 + ++$position;
117 + }
118 + add_menu_page( 'TablePress', $admin_menu_entry_name, $min_access_cap, 'tablepress', $callback, $icon_url, $position ); // @phpstan-ignore argument.type
116 119 foreach ( $this->view_actions as $action => $entry ) {
117 120 if ( ! $entry['show_entry'] ) {
118 121 continue;
119 122 }
@@ -120,17 +123,17 @@
120 123 $slug = 'tablepress';
121 124 if ( 'list' !== $action ) {
122 125 $slug .= '_' . $action;
123 126 }
124 - // @phpstan-ignore-next-line
125 - $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 );
127 + /* translators: %1$s: Page title, %2$s: Plugin name (TablePress) */
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 ); // @phpstan-ignore argument.type, argument.type
126 129 if ( false !== $page_hook ) {
127 130 $this->page_hooks[] = $page_hook;
128 131 }
129 132 }
130 133 } else {
131 - // @phpstan-ignore-next-line
132 - $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 );
133 136 if ( false !== $page_hook ) {
134 137 $this->page_hooks[] = $page_hook;
135 138 }
136 139 }
@@ -175,13 +178,8 @@
175 178 add_action( 'admin_bar_menu', array( $this, 'add_wp_admin_bar_new_content_menu_entry' ), 71 );
176 179 }
177 180
178 181 add_action( 'load-plugins.php', array( $this, 'plugins_page' ) );
179 -
180 - // Add filters and actions for the integration into the WP WXR exporter and importer.
181 - add_action( 'wp_import_insert_post', array( TablePress::$model_table, 'add_table_id_on_wp_import' ), 10, 4 );
182 - add_filter( 'wp_import_post_meta', array( TablePress::$model_table, 'prevent_table_id_post_meta_import_on_wp_import' ), 10, 3 );
183 - add_filter( 'wxr_export_skip_postmeta', array( TablePress::$model_table, 'add_table_id_to_wp_export' ), 10, 3 );
184 182 }
185 183
186 184 /**
187 185 * Loads additional JavaScript code for the TablePress table block (in the block editor context).
@@ -188,8 +186,16 @@
188 186 *
189 187 * @since 2.2.0
190 188 */
191 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 +
192 198 // Add table information for the block editor to the page.
193 199 $handle = generate_block_asset_handle( 'tablepress/table', 'editorScript' );
194 200 $data = $this->get_block_editor_data();
195 201 wp_add_inline_script( $handle, $data, 'before' );
@@ -202,9 +208,9 @@
202 208 */
203 209 public function enqueue_block_assets(): void {
204 210 // Load the TablePress default CSS and the user's "Custom CSS" in the block editor iframe.
205 211 if ( is_admin() ) {
206 - TablePress::$controller->enqueue_css();
212 + TablePress::$controller->maybe_enqueue_css();
207 213 }
208 214 }
209 215
210 216 /**
@@ -241,26 +247,26 @@
241 247 * @param array<string, string> $tables List of table names, the table ID is the array key.
242 248 */
243 249 $tables = apply_filters( 'tablepress_block_editor_tables_list', $tables );
244 250
245 - $tables = wp_json_encode( $tables, TABLEPRESS_JSON_OPTIONS );
251 + $tables = wp_json_encode( $tables, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES );
246 252 if ( false === $tables ) {
247 253 // JSON encoding failed, return an error object. Use a prefixed "_error" key to avoid conflicts with intentionally added "error" keys.
248 254 $tables = '{ "_error": "The data could not be encoded to JSON!" }';
249 255 }
250 - // Print them inside a `JSON.parse()` call in JS for speed gains, with necessary escaping of `</script>`, `'`, and `\`.
251 - $tables = str_replace( array( '</script>', '\\', "'" ), array( '<\/script>', '\\\\', "\'" ), $tables );
256 + // Print the JSON data inside a `JSON.parse()` call in JS for speed gains, with necessary escaping of `\` and `'`.
257 + $tables = str_replace( array( '\\', "'" ), array( '\\\\', "\'" ), $tables );
252 258
253 259 $shortcode = esc_js( TablePress::$shortcode );
254 260
255 261 $template = TablePress::$model_table->get_table_template();
256 - $template = wp_json_encode( $template['options'], TABLEPRESS_JSON_OPTIONS );
262 + $template = wp_json_encode( $template['options'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES );
257 263 if ( false === $template ) {
258 264 // JSON encoding failed, return an error object. Use a prefixed "_error" key to avoid conflicts with intentionally added "error" keys.
259 265 $template = '{ "_error": "The data could not be encoded to JSON!" }';
260 266 }
261 - // Print them inside a `JSON.parse()` call in JS for speed gains, with necessary escaping of `</script>`, `'`, and `\`.
262 - $template = str_replace( array( '</script>', '\\', "'" ), array( '<\/script>', '\\\\', "\'" ), $template );
267 + // Print the JSON data inside a `JSON.parse()` call in JS for speed gains, with necessary escaping of `\` and `'`.
268 + $template = str_replace( array( '\\', "'" ), array( '\\\\', "\'" ), $template );
263 269
264 270 /**
265 271 * Filters whether the table block preview should be loaded via a <ServerSideRender> in the block editor.
266 272 *
@@ -276,17 +282,17 @@
276 282 $url = TablePress::url( array( 'action' => 'list' ) );
277 283 }
278 284
279 285 return <<<JS
280 -// Ensure the global `tp` object exists.
281 -window.tp = window.tp || {};
282 -tp.url = '{$url}';
283 -tp.load_block_preview = {$load_block_preview};
284 -tp.table = {};
285 -tp.table.shortcode = '{$shortcode}';
286 -tp.table.template = JSON.parse( '{$template}' );
287 -tp.tables = JSON.parse( '{$tables}' );
288 -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;
289 295 }
290 296
291 297 /**
292 298 * Register actions to add "Table" button to "HTML editor" and "Visual editor" toolbars.
@@ -298,9 +304,9 @@
298 304 return;
299 305 }
300 306
301 307 // Only load the toolbar integration if the Block Editor is not used.
302 - if ( TablePress::site_uses_block_editor() ) {
308 + if ( 'block' === TablePress::site_used_editor() ) {
303 309 return;
304 310 }
305 311
306 312 add_thickbox(); // The files are usually already loaded by media upload functions.
@@ -314,9 +320,9 @@
314 320 'title' => __( 'Insert a TablePress table', 'tablepress' ),
315 321 'thickbox_title' => __( 'Insert a TablePress table', 'tablepress' ),
316 322 'thickbox_url' => TablePress::url( array( 'action' => 'editor_button_thickbox' ), true, 'admin-post.php' ),
317 323 ),
318 - )
324 + ),
319 325 );
320 326
321 327 // TinyMCE integration.
322 328 if ( user_can_richedit() ) {
@@ -370,9 +376,9 @@
370 376
371 377 $wp_admin_bar->add_menu( array(
372 378 'parent' => 'new-content',
373 379 'id' => 'new-tablepress-table',
374 - 'title' => __( 'TablePress Table', 'tablepress' ),
380 + 'title' => __( 'TablePress table', 'tablepress' ),
375 381 'href' => TablePress::url( array( 'action' => 'add' ) ),
376 382 ) );
377 383 }
378 384
@@ -384,8 +390,21 @@
384 390 public function plugins_page(): void {
385 391 // Add additional links on Plugins page.
386 392 add_filter( 'plugin_action_links_' . TABLEPRESS_BASENAME, array( $this, 'add_plugin_action_links' ) );
387 393 add_filter( 'plugin_row_meta', array( $this, 'add_plugin_row_meta' ), 10, 2 );
394 + $incompatible_superseded_extensions = array(
395 + 'tablepress-datatables-alphabetsearch/tablepress-datatables-alphabetsearch.php',
396 + 'tablepress-datatables-column-filter-widgets/tablepress-datatables-column-filter-widgets.php',
397 + 'tablepress-datatables-columnfilter/tablepress-datatables-columnfilter.php',
398 + 'tablepress-datatables-fixedcolumns/tablepress-datatables-fixedcolumns.php',
399 + 'tablepress-datatables-inverted-filter/tablepress-datatables-inverted-filter.php',
400 + 'tablepress-datatables-row-details/tablepress-datatables-row-details.php',
401 + 'tablepress-datatables-rowgroup/tablepress-datatables-rowgroup.php',
402 + 'tablepress-responsive-tables/tablepress-responsive-tables.php',
403 + );
404 + foreach ( $incompatible_superseded_extensions as $plugin_file ) {
405 + add_action( "after_plugin_row_{$plugin_file}", array( $this, 'add_superseded_extension_meta_row' ), 10, 3 );
406 + }
388 407 }
389 408
390 409 /**
391 410 * Add links to the TablePress entry in the "Plugin" column on the Plugins page.
@@ -396,9 +415,9 @@
396 415 * @return string[] Extended list of links to print in the "Plugin" column on the Plugins page.
397 416 */
398 417 public function add_plugin_action_links( array $links ): array {
399 418 if ( current_user_can( 'tablepress_list_tables' ) ) {
400 - $links[] = '<a href="' . TablePress::url() . '">' . __( 'Plugin page', 'tablepress' ) . '</a>';
419 + $links[] = '<a href="' . esc_url( TablePress::url() ) . '">' . __( 'Plugin page', 'tablepress' ) . '</a>';
401 420 }
402 421 return $links;
403 422 }
404 423
@@ -423,8 +442,54 @@
423 442 return $links;
424 443 }
425 444
426 445 /**
446 + * Prints a superseded extension notice below certain TablePress Extension plugins' meta rows on the "Plugins" screen.
447 + *
448 + * @since 2.4.1
449 + *
450 + * @param string $plugin_file Path to the plugin file relative to the plugins directory.
451 + * @param array<int, string|string[]|bool> $plugin_data An array of plugin data.
452 + * @param string $status Status filter currently applied to the plugin list.
453 + */
454 + public function add_superseded_extension_meta_row( string $plugin_file, array $plugin_data, string $status ): void {
455 + if ( ! is_plugin_active( $plugin_file ) ) {
456 + return;
457 + }
458 + ?>
459 + <tr class="plugin-update-tr active">
460 + <td colspan="<?php echo esc_attr( $GLOBALS['wp_list_table']->get_column_count() ); ?>" class="plugin-update colspanchange">
461 + <div class="update-message notice inline notice-error notice-alt">
462 + <?php
463 + if ( tb_tp_fs()->is_free_plan() ) {
464 + echo '<p style="font-size:14px;">';
465 + _e( 'This TablePress Extension was retired.', 'tablepress' );
466 + echo ' ';
467 + _e( '<strong>The plugin does no longer work with TablePress 3</strong> and will no longer receive updates or support!', 'tablepress' );
468 + echo '<br>';
469 + _e( 'Keeping it activated can lead to errors on your website!', 'tablepress' );
470 + 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>';
471 + echo '</p>';
472 + }
473 + ?>
474 + <style>
475 + /* Remove the separator line between the plugin's and the notice's table row. */
476 + .plugins .active[data-plugin="<?php echo $plugin_file; ?>"] th,
477 + .plugins .active[data-plugin="<?php echo $plugin_file; ?>"] td {
478 + box-shadow: none;
479 + }
480 + /* Hide the plugin update row for the Extension as those won't work anymore anyways. */
481 + .plugins .plugin-update-tr[data-plugin="<?php echo $plugin_file; ?>"] {
482 + display: none;
483 + }
484 + </style>
485 + </div>
486 + </td>
487 + </tr>
488 + <?php
489 + }
490 +
491 + /**
427 492 * Prepare the rendering of an admin screen, by determining the current action, loading necessary data and initializing the view.
428 493 *
429 494 * @since 1.0.0
430 495 */
@@ -430,9 +495,9 @@
430 495 */
431 496 public function load_admin_page(): void {
432 497 // Determine the action from either the GET parameter (for sub-menu entries, and the main admin menu entry).
433 498 $action = ( ! empty( $_GET['action'] ) ) ? $_GET['action'] : 'list'; // Default action is list.
434 - if ( $this->is_top_level_page ) {
499 + if ( TablePress::$controller->is_top_level_page ) {
435 500 // Or, for sub-menu entry of an admin menu "TablePress" entry, get it from the "page" GET parameter.
436 501 if ( 'tablepress' !== $_GET['page'] ) {
437 502 // Actions that are top-level entries, but don't have an action GET parameter (action is after last _ in string).
438 503 $action = substr( $_GET['page'], 11 ); // $_GET['page'] has the format 'tablepress_{$action}'
@@ -439,9 +504,9 @@
439 504 }
440 505 }
441 506
442 507 // Check if action is a supported action, and whether the user is allowed to access this screen.
443 - 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.)
508 + 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.)
444 509 wp_die( __( 'Sorry, you are not allowed to access this page.', 'default' ), 403 );
445 510 }
446 511
447 512 // Don't load TablePress assets on the Freemius opt-in/activation screen.
@@ -461,12 +526,12 @@
461 526 }
462 527
463 528 // Pre-define some view data.
464 529 $data = array(
465 - 'view_actions' => $this->view_actions,
466 - 'message' => ( ! empty( $_GET['message'] ) ) ? $_GET['message'] : false,
467 - 'error_details' => ( ! empty( $_GET['error_details'] ) ) ? $_GET['error_details'] : '',
468 - 'site_uses_block_editor' => TablePress::site_uses_block_editor(),
530 + 'view_actions' => $this->view_actions,
531 + 'message' => ( ! empty( $_GET['message'] ) ) ? $_GET['message'] : false,
532 + 'error_details' => ( ! empty( $_GET['error_details'] ) ) ? $_GET['error_details'] : '',
533 + 'site_used_editor' => TablePress::site_used_editor(),
469 534 );
470 535
471 536 // Depending on the action, load more necessary data for the corresponding view.
472 537 switch ( $action ) {
@@ -473,11 +538,12 @@
473 538 case 'list':
474 539 $data['table_id'] = ( ! empty( $_GET['table_id'] ) ) ? $_GET['table_id'] : false;
475 540 // Prime the post meta cache for cached loading of last_editor.
476 541 $data['table_ids'] = TablePress::$model_table->load_all( true );
477 - $data['messages']['donation_message'] = $this->maybe_show_donation_message();
478 - $data['messages']['first_visit'] = ! $data['messages']['donation_message'] && TablePress::$model_options->get( 'message_first_visit' );
479 - $data['messages']['plugin_update_message'] = TablePress::$model_options->get( 'message_plugin_update' );
542 + $data['messages']['donation_nag'] = $this->maybe_show_donation_message();
543 + $data['messages']['first_visit'] = ! $data['messages']['donation_nag'] && TablePress::$model_options->get( 'message_first_visit' );
544 + $data['messages']['plugin_update'] = TablePress::$model_options->get( 'message_plugin_update' );
545 + $data['messages']['superseded_extensions'] = current_user_can( 'manage_options' ) && TablePress::$model_options->get( 'message_superseded_extensions' );
480 546 $data['table_count'] = count( $data['table_ids'] );
481 547 break;
482 548 case 'about':
483 549 $data['first_activation'] = TablePress::$model_options->get( 'first_activation' );
@@ -488,9 +554,9 @@
488 554 * (called here, as the credentials form posts to this handler again, due to how `request_filesystem_credentials()` works)
489 555 */
490 556 if ( isset( $_GET['item'] ) && 'save_custom_css' === $_GET['item'] ) {
491 557 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.
492 - $action = 'options_custom_css'; // to load a different view
558 + $action = 'options_custom_css'; // To load a different view.
493 559 // Try saving "Custom CSS" to a file, otherwise this gets the HTML for the credentials form.
494 560 $tablepress_css = TablePress::load_class( 'TablePress_CSS', 'class-css.php', 'classes' );
495 561 $result = $tablepress_css->save_custom_css_to_file_plugin_options( TablePress::$model_options->get( 'custom_css' ), TablePress::$model_options->get( 'custom_css_minified' ) );
496 562 if ( is_string( $result ) ) {
@@ -511,9 +577,9 @@
511 577 break;
512 578 }
513 579 $data['frontend_options']['use_custom_css'] = TablePress::$model_options->get( 'use_custom_css' );
514 580 $data['frontend_options']['custom_css'] = TablePress::$model_options->get( 'custom_css' );
515 - $data['user_options']['parent_page'] = $this->parent_page;
581 + $data['user_options']['parent_page'] = TablePress::$controller->parent_page;
516 582 break;
517 583 case 'edit':
518 584 if ( empty( $_GET['table_id'] ) ) {
519 585 TablePress::redirect( array( 'action' => 'list', 'message' => 'error_no_table' ) );
@@ -805,10 +871,10 @@
805 871
806 872 $add_table = wp_unslash( $_POST['table'] );
807 873
808 874 // Perform confidence checks of posted data.
809 - $name = ( isset( $add_table['name'] ) ) ? $add_table['name'] : '';
810 - $description = ( isset( $add_table['description'] ) ) ? $add_table['description'] : '';
875 + $name = $add_table['name'] ?? '';
876 + $description = $add_table['description'] ?? '';
811 877 if ( ! isset( $add_table['rows'], $add_table['columns'] ) ) {
812 878 TablePress::redirect( array( 'action' => 'add', 'message' => 'error_add', 'error_details' => 'The HTTP POST data does not contain the table size.' ) );
813 879 }
814 880
@@ -868,10 +934,10 @@
868 934 if ( ! empty( $posted_options['admin_menu_parent_page'] ) && '-' !== $posted_options['admin_menu_parent_page'] ) {
869 935 $new_options['admin_menu_parent_page'] = $posted_options['admin_menu_parent_page'];
870 936 // Re-init parent information, as `TablePress::redirect()` URL might be wrong otherwise.
871 937 /** This filter is documented in classes/class-controller.php */
872 - $this->parent_page = apply_filters( 'tablepress_admin_menu_parent_page', $posted_options['admin_menu_parent_page'] );
873 - $this->is_top_level_page = in_array( $this->parent_page, array( 'top', 'middle', 'bottom' ), true );
938 + TablePress::$controller->parent_page = apply_filters( 'tablepress_admin_menu_parent_page', $posted_options['admin_menu_parent_page'] );
939 + TablePress::$controller->is_top_level_page = in_array( TablePress::$controller->parent_page, array( 'top', 'middle', 'bottom' ), true );
874 940 }
875 941
876 942 // Custom CSS can only be saved if the user is allowed to do so.
877 943 $update_custom_css_files = false;
@@ -882,13 +948,20 @@
882 948 if ( isset( $posted_options['custom_css'] ) ) {
883 949 $new_options['custom_css'] = $posted_options['custom_css'];
884 950
885 951 $tablepress_css = TablePress::load_class( 'TablePress_CSS', 'class-css.php', 'classes' );
886 - // Sanitize and tidy up Custom CSS.
887 - $new_options['custom_css'] = $tablepress_css->sanitize_css( $new_options['custom_css'] );
888 - // Minify Custom CSS.
889 - $new_options['custom_css_minified'] = $tablepress_css->minify_css( $new_options['custom_css'] );
890 952
953 + if ( '' !== $new_options['custom_css'] ) {
954 + // Update "Custom CSS" to use DataTables 2 variants instead of old DataTables 1.x CSS classes.
955 + $new_options['custom_css'] = TablePress::convert_datatables_api_data( $new_options['custom_css'] );
956 + // Sanitize and tidy up Custom CSS.
957 + $new_options['custom_css'] = $tablepress_css->sanitize_css( $new_options['custom_css'] );
958 + // Minify Custom CSS.
959 + $new_options['custom_css_minified'] = $tablepress_css->minify_css( $new_options['custom_css'] );
960 + } else {
961 + $new_options['custom_css_minified'] = '';
962 + }
963 +
891 964 // Maybe update CSS files as well.
892 965 $custom_css_file_contents = $tablepress_css->load_custom_css_from_file( 'normal' );
893 966 if ( false === $custom_css_file_contents ) {
894 967 $custom_css_file_contents = '';
@@ -1015,9 +1088,9 @@
1015 1088 /** This filter is documented in controllers/controller-admin.php */
1016 1089 $download_filename = apply_filters( 'tablepress_export_filename', $download_filename, '', '', $export['format'], $export_to_zip );
1017 1090 $download_filename = sanitize_file_name( $download_filename );
1018 1091 $full_filename = wp_tempnam( $download_filename );
1019 - if ( true !== $zip_file->open( $full_filename, ZIPARCHIVE::OVERWRITE ) ) {
1092 + if ( true !== $zip_file->open( $full_filename, ZipArchive::OVERWRITE ) ) {
1020 1093 @unlink( $full_filename ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1021 1094 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.' ) );
1022 1095 }
1023 1096
@@ -1047,9 +1120,9 @@
1047 1120 }
1048 1121
1049 1122 // If something went wrong, or no files were added to the ZIP file, bail out.
1050 1123 // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
1051 - if ( ZIPARCHIVE::ER_OK !== $zip_file->status || 0 === $zip_file->numFiles ) {
1124 + if ( ZipArchive::ER_OK !== $zip_file->status || 0 === $zip_file->numFiles ) {
1052 1125 $zip_file->close();
1053 1126 @unlink( $full_filename ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1054 1127 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.' ) );
1055 1128 }
@@ -1316,14 +1389,15 @@
1316 1389 $render_options = shortcode_atts( $default_render_options, $table['options'] );
1317 1390 /** This filter is documented in controllers/controller-frontend.php */
1318 1391 $render_options = apply_filters( 'tablepress_shortcode_table_shortcode_atts', $render_options );
1319 1392 $render_options['html_id'] = "tablepress-{$table['id']}";
1393 + $render_options['block_preview'] = true;
1320 1394 $_render->set_input( $table, $render_options );
1321 1395 $view_data = array(
1322 - 'table_id' => $table_id,
1323 - 'head_html' => $_render->get_preview_css(),
1324 - 'body_html' => $_render->get_output( 'html' ),
1325 - 'site_uses_block_editor' => TablePress::site_uses_block_editor(),
1396 + 'table_id' => $table_id,
1397 + 'head_html' => $_render->get_preview_css(),
1398 + 'body_html' => $_render->get_output( 'html' ),
1399 + 'site_used_editor' => TablePress::site_used_editor(),
1326 1400 );
1327 1401
1328 1402 $custom_css = TablePress::$model_options->get( 'custom_css' );
1329 1403 $use_custom_css = ( TablePress::$model_options->get( 'use_custom_css' ) && '' !== $custom_css );
@@ -1386,9 +1460,9 @@
1386 1460
1387 1461 TablePress::$model_table->destroy();
1388 1462 TablePress::$model_options->destroy();
1389 1463
1390 - $output = '<strong>' . __( 'TablePress was uninstalled successfully.', 'tablepress' ) . '</strong><br /><br />';
1464 + $output = '<strong>' . __( 'TablePress was uninstalled successfully.', 'tablepress' ) . '</strong><br><br>';
1391 1465 $output .= __( 'All tables, data, and options were deleted.', 'tablepress' );
1392 1466 if ( is_multisite() ) {
1393 1467 $output .= ' ' . __( 'You may now ask the network admin to delete the plugin&#8217;s folder <code>tablepress</code> from the server, if no other site in the network uses it.', 'tablepress' );
1394 1468 } else {