/** * 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) { wp_nonce_field(TablePress::nonce($this->action)); echo "\n"; }
/** * Print hidden field with a nonce for the screen's action, to be transmitted in HTTP requests * * @since 1.0.0 * @uses wp_nonce_field() * * @param array $data Data for this screen * @param array $box Information about the text box */ protected function action_nonce_field(array $data, array $box) { // use custom nonce field here, that includes the table ID wp_nonce_field(TablePress::nonce($this->action, $data['table']['id']), 'nonce-edit-table'); echo "\n"; wp_nonce_field(TablePress::nonce('preview_table', $data['table']['id']), 'nonce-preview-table', false, true); }
/** * Save the table after the "Save Changes" button on the "Edit" screen has been clicked. * * @since 1.0.0 */ public function ajax_action_save_table() { if (empty($_POST['tablepress']) || empty($_POST['tablepress']['id'])) { wp_die('-1'); } else { $edit_table = wp_unslash($_POST['tablepress']); } // Check if the submitted nonce matches the generated nonce we created earlier, dies -1 on failure. TablePress::check_nonce('edit', $edit_table['id'], '_ajax_nonce', true); // Ignore the request if the current user doesn't have sufficient permissions. if (!current_user_can('tablepress_edit_table', $edit_table['id'])) { wp_die('-1'); } // Default response data. $success = false; $message = 'error_save'; $error_details = ''; do { // to be able to "break;" (allows for better readable code) // Load table, without table data, but with options and visibility settings. $existing_table = TablePress::$model_table->load($edit_table['id'], false, true); if (is_wp_error($existing_table)) { // maybe somehow load a new table here? (TablePress::$model_table->get_table_template())? // Add an error code to the existing WP_Error. $existing_table->add('ajax_save_table_load', '', $edit_table['id']); $error_details = $this->get_wp_error_string($existing_table); break; } // Check and convert data that was transmitted as JSON. if (empty($edit_table['data']) || empty($edit_table['options']) || empty($edit_table['visibility'])) { // Create a new WP_Error. $empty_data_error = new WP_Error('ajax_save_table_data_empty', '', $edit_table['id']); $error_details = $this->get_wp_error_string($empty_data_error); break; } $edit_table['data'] = (array) json_decode($edit_table['data'], true); $edit_table['options'] = (array) json_decode($edit_table['options'], true); $edit_table['visibility'] = (array) json_decode($edit_table['visibility'], true); // Check consistency of new table, and then merge with existing table. $table = TablePress::$model_table->prepare_table($existing_table, $edit_table, true, true); if (is_wp_error($table)) { // Add an error code to the existing WP_Error. $table->add('ajax_save_table_prepare', '', $edit_table['id']); $error_details = $this->get_wp_error_string($table); break; } // DataTables Custom Commands can only be edit by trusted users. if (!current_user_can('unfiltered_html')) { $table['options']['datatables_custom_commands'] = $existing_table['options']['datatables_custom_commands']; } // Save updated table. $saved = TablePress::$model_table->save($table); if (is_wp_error($saved)) { // Add an error code to the existing WP_Error. $saved->add('ajax_save_table_save', '', $table['id']); $error_details = $this->get_wp_error_string($saved); break; } // At this point, the table was saved successfully, possible ID change remains. $success = true; $message = 'success_save'; // Check if ID change is desired. if ($table['id'] === $table['new_id']) { // If not, we are done. break; } // Change table ID. if (current_user_can('tablepress_edit_table_id', $table['id'])) { $id_changed = TablePress::$model_table->change_table_id($table['id'], $table['new_id']); if (!is_wp_error($id_changed)) { $message = 'success_save_success_id_change'; $table['id'] = $table['new_id']; } else { $message = 'success_save_error_id_change'; // Add an error code to the existing WP_Error. $id_changed->add('ajax_save_table_id_change', '', $table['new_id']); $error_details = $this->get_wp_error_string($id_changed); } } else { $message = 'success_save_error_id_change'; $error_details = 'table_id_could_not_be_changed: capability_check_failed'; } } while (false); // Do-while-loop through this exactly once, to be able to "break;" early. // Generate the response. // Common data for all responses. $response = array('success' => $success, 'message' => $message); if ($success) { $response['table_id'] = $table['id']; $response['new_edit_nonce'] = wp_create_nonce(TablePress::nonce('edit', $table['id'])); $response['new_preview_nonce'] = wp_create_nonce(TablePress::nonce('preview_table', $table['id'])); $response['last_modified'] = TablePress::format_datetime($table['last_modified']); $response['last_editor'] = TablePress::get_user_display_name($table['options']['last_editor']); } if (!empty($error_details)) { $response['error_details'] = esc_html($error_details); } // Buffer all outputs, to prevent errors/warnings being printed that make the JSON invalid. $output_buffer = ob_get_clean(); if (!empty($output_buffer)) { $response['output_buffer'] = $output_buffer; } // Send the response. wp_send_json($response); }
/** * Test that names of nonces are generated properly. * * @since 1.1.0 */ public function test_nonce() { $this->assertSame('tablepress_foo_bar', TablePress::nonce('foo', 'bar')); $this->assertSame('tablepress_foo', TablePress::nonce('foo')); $this->assertSame('tablepress_foo', TablePress::nonce('foo', false)); }
/** * Render the current view. * * @since 1.0.0 */ public function render() { _wp_admin_html_begin(); wp_print_styles('colors'); wp_print_scripts('jquery'); ?> <title><?php printf(__('%1$s ‹ %2$s', 'tablepress'), __('List of Tables', 'tablepress'), 'TablePress'); ?> </title> <style type="text/css"> /* Account for .wp-toolbar */ html { padding-top: 0 !important; } body { margin: 0 0 15px 15px; } /* Fix search field positioning */ #tablepress-page .search-box { position: relative; height: auto; width: auto; float: right; clear: none; margin: 0; } #tablepress-page .subtitle { float: left; padding: 10px 0 0; } #tablepress-page .search-box input[name="s"] { float: left; width: auto; } /* Fix pagination layout */ #tablepress-page .tablenav-pages { text-align: left; } #tablepress-page .tablenav .tablenav-pages a { padding: 5px 12px; font-size: 16px; } #tablepress-page .tablenav-pages .pagination-links .paging-input { font-size: 16px; } #tablepress-page .tablenav-pages .pagination-links .current-page { padding: 4px; font-size: 16px; } /* Width and font weight for the columns */ .tablepress-editor-button-list thead .column-table_id { width: 50px; } .tablepress-editor-button-list tbody .column-table_id, .tablepress-editor-button-list tbody .column-table_name { font-weight: bold; } .tablepress-editor-button-list thead .column-table_action { width: 150px; } .tablepress-editor-button-list tbody .column-table_action { padding: 4px 7px 1px; vertical-align: middle; } /* Shortcode input field */ #tablepress-page .table-shortcode-inline { background: transparent; border: none; color: #333333; width: 110px; margin: 0; padding: 0; font-weight: bold; font-size: 14px; -webkit-box-shadow: none; box-shadow: none; text-align: center; vertical-align: top; } #tablepress-page .table-shortcode { cursor: text; } <?php if (is_rtl()) { ?> /* RTL CSS */ body.rtl { margin: 0 15px 15px 0; } .rtl #tablepress-page .search-box { float: left; } .rtl #tablepress-page .subtitle { float: right; } .rtl #tablepress-page .search-box input[name="s"] { float: right; } .rtl #tablepress-page .table-shortcode-inline { width: 125px; font-size: 13px; vertical-align: baseline; } <?php } ?> </style> </head> <body class="wp-admin wp-core-ui js iframe<?php echo is_rtl() ? ' rtl' : ''; ?> "> <div id="tablepress-page" class="wrap"> <h2><?php printf(__('%1$s ‹ %2$s', 'tablepress'), __('List of Tables', 'tablepress'), 'TablePress'); ?> </h2> <div id="poststuff"> <p> <?php _e('This is a list of all available tables.', 'tablepress'); ?> <?php _e('You may insert a table into a post or page here.', 'tablepress'); ?> </p><p> <?php printf(__('Click the “%1$s” button for the desired table to automatically insert the<br />corresponding Shortcode (%2$s) into the editor.', 'tablepress'), __('Insert Shortcode', 'tablepress'), '<input type="text" class="table-shortcode table-shortcode-inline ltr" value="' . esc_attr('[' . TablePress::$shortcode . ' id=<ID> /]') . '" readonly="readonly" />'); ?> </p> <?php if (!empty($_GET['s'])) { printf('<span class="subtitle">' . __('Search results for “%s”', 'tablepress') . '</span>', esc_html(wp_unslash($_GET['s']))); } ?> <form method="get" action=""> <input type="hidden" name="action" value="tablepress_<?php echo $this->action; ?> " /> <?php wp_nonce_field(TablePress::nonce($this->action), '_wpnonce', false); echo "\n"; ?> <?php $this->wp_list_table->search_box(__('Search Tables', 'tablepress'), 'tables_search'); ?> </form> <?php $this->wp_list_table->display(); ?> </div> </div> <script type="text/javascript"> jQuery( document ).ready( function( $ ) { $( '.tablepress-editor-button-list' ).on( 'click', '.insert-shortcode', function() { var win = window.dialogArguments || opener || parent || top; win.send_to_editor( $(this).attr( 'title' ) ); } ); } ); </script> </body> </html> <?php }
/** * Render the current view * * @since 1.0.0 */ public function render() { _wp_admin_html_begin(); wp_print_styles('colors'); wp_print_scripts('jquery'); ?> <title><?php printf(__('%1$s ‹ %2$s', 'tablepress'), __('List of Tables', 'tablepress'), 'TablePress'); ?> </title> <style type="text/css"> body { margin: -26px 0px 15px 15px; /* top has -28px offset to account for html.wp-toolbar */ } #icon-tablepress { background: transparent url(<?php echo plugins_url('admin/tablepress-icon.png', TABLEPRESS__FILE__); ?> ) no-repeat; } /* HiDPI images */ @media print, (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) { /* Screen icon */ #icon-tablepress { background-image: url(<?php echo plugins_url('admin/tablepress-icon-2x.png', TABLEPRESS__FILE__); ?> ); background-size: 36px 36px; } } /* width and font weight for the columns */ .tablepress-editor-button-list thead .column-table_id { width: 50px; } .tablepress-editor-button-list tbody .column-table_id, .tablepress-editor-button-list tbody .column-table_name { font-weight: bold; } .tablepress-editor-button-list thead .column-table_action { width: 150px; } .tablepress-editor-button-list tbody .column-table_action { padding: 4px 7px; } #tablepress-page .table-shortcode-inline { background: transparent; border: none; color: #333333; width: 90px; margin: 0; padding: 0; font-weight: bold; -webkit-box-shadow: none; box-shadow: none; } #tablepress-page .table-shortcode { cursor: text; } /* Search results for WP_List_Table */ #tablepress-page .subtitle { float: left; padding-left: 0px; } </style> </head> <body class="wp-admin wp-core-ui js iframe"> <div id="tablepress-page" class="wrap"> <?php screen_icon('tablepress'); ?> <h2><?php printf(__('%1$s ‹ %2$s', 'tablepress'), __('List of Tables', 'tablepress'), 'TablePress'); ?> </h2> <div id="poststuff"> <p> <?php _e('This is a list of all available tables.', 'tablepress'); ?> <?php _e('You may insert a table into a post or page here.', 'tablepress'); ?> </p><p> <?php printf(__('Click the “%1$s” button for the desired table to automatically insert the<br />corresponding Shortcode (%2$s) into the editor.', 'tablepress'), __('Insert Shortcode', 'tablepress'), '<input type="text" class="table-shortcode table-shortcode-inline" value="[' . TablePress::$shortcode . ' id=<ID> /]" readonly="readonly" />'); ?> </p> <?php if (!empty($_GET['s'])) { printf('<span class="subtitle">' . __('Search results for “%s”', 'tablepress') . '</span>', esc_html(stripslashes($_GET['s']))); } ?> <form method="get" action=""> <input type="hidden" name="action" value="tablepress_<?php echo $this->action; ?> " /> <?php wp_nonce_field(TablePress::nonce($this->action), '_wpnonce', false); echo "\n"; ?> <?php $this->wp_list_table->search_box(__('Search Tables', 'tablepress'), 'tables_search'); ?> </form> <?php $this->wp_list_table->display(); ?> </div> </div> <script type="text/javascript"> jQuery(document).ready( function($) { $( '.tablepress-editor-button-list' ).on( 'click', '.insert-shortcode', function() { var win = window.dialogArguments || opener || parent || top; win.send_to_editor( $(this).attr( 'title' ) ); } ); } ); </script> </body> </html> <?php }
/** * Save the table after the "Save Changes" button on the "Edit" screen has been clicked * * @since 1.0.0 */ public function ajax_action_save_table() { if (empty($_POST['tablepress']) || empty($_POST['tablepress']['id'])) { wp_die('-1'); } else { $edit_table = stripslashes_deep($_POST['tablepress']); } // check to see if the submitted nonce matches with the generated nonce we created earlier, dies -1 on fail TablePress::check_nonce('edit', $edit_table['id'], '_ajax_nonce', true); // ignore the request if the current user doesn't have sufficient permissions if (!current_user_can('tablepress_edit_table', $edit_table['id'])) { wp_die('-1'); } // default response data: $success = false; $message = 'error_save'; do { // to be able to "break;" (allows for better readable code) // Load existing table from DB $existing_table = $this->model_table->load($edit_table['id']); if (false === $existing_table) { // maybe somehow load a new table here? ($this->model_table->get_table_template())? break; } // Check and convert data that was transmitted as JSON if (empty($edit_table['data']) || empty($edit_table['options']) || empty($edit_table['visibility'])) { break; } $edit_table['data'] = json_decode($edit_table['data'], true); $edit_table['options'] = json_decode($edit_table['options'], true); $edit_table['visibility'] = json_decode($edit_table['visibility'], true); // Check consistency of new table, and then merge with existing table $table = $this->model_table->prepare_table($existing_table, $edit_table, true, true); if (false === $table) { break; } // DataTables Custom Commands can only be edit by trusted users if (!current_user_can('unfiltered_html')) { $table['options']['datatables_custom_commands'] = $existing_table['options']['datatables_custom_commands']; } // Save updated table $saved = $this->model_table->save($table); if (false === $saved) { break; } // at this point, the table was saved successfully, possible ID change remains $success = true; $message = 'success_save'; // Check if ID change is desired if ($table['id'] === $table['new_id']) { // if not, we are done break; } // Change table ID if (current_user_can('tablepress_edit_table_id', $table['id'])) { $id_changed = $this->model_table->change_table_id($table['id'], $table['new_id']); } else { $id_changed = false; } if ($id_changed) { $message = 'success_save_success_id_change'; $table['id'] = $table['new_id']; } else { $message = 'success_save_error_id_change'; } } while (false); // do-while-loop through this exactly once, to be able to "break;" early // Generate the response $response = array('success' => $success, 'message' => $message); if ($success) { $response['table_id'] = $table['id']; $response['new_edit_nonce'] = wp_create_nonce(TablePress::nonce('edit', $table['id'])); $response['new_preview_nonce'] = wp_create_nonce(TablePress::nonce('preview_table', $table['id'])); $response['last_modified'] = TablePress::format_datetime($table['last_modified']); $response['last_editor'] = TablePress::get_user_display_name($table['options']['last_editor']); } // Send the response $response['output_buffer'] = ob_get_clean(); // buffer all outputs, to prevent errors/warnings being printed that make the JSON invalid wp_send_json($response); }