PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.84
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.84
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
wp-data-access / WPDataAccess / CSV_Files / WPDA_CSV_List_Table.php

WPDA_CSV_List_Table.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.84, at WPDataAccess/CSV_Files/WPDA_CSV_List_Table.php

371 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDataAccess\CSV_Files {
4
5 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
6 use WPDataAccess\List_Table\WPDA_List_Table;
7 use WPDataAccess\Plugin_Table_Models\WPDA_CSV_Uploads_Model;
8 use WPDataAccess\Utilities\WPDA_Message_Box;
9 use WPDataAccess\WPDA;
10
11 /**
12 * List table showing upload CSV files
13 */
14 class WPDA_CSV_List_Table extends WPDA_List_Table {
15
16 /**
17 * Constructor
18 *
19 * @param array $args Constructor arguments.
20 */
21 public function __construct( $args = array() ) {
22 $args['column_headers'] = self::column_headers_labels();
23 $args['title'] = '';
24 $args['subtitle'] = '';
25 $args['show_view_link'] = 'off';
26 $args['allow_insert'] = 'off';
27 $args['allow_update'] = 'off';
28 $args['allow_delete'] = 'on';
29 $args['allow_import'] = 'off';
30 $args['show_page_title'] = false;
31
32 global $wpdb;
33
34 $args['wpdaschema_name'] = $wpdb->dbname;
35 $args['table_name'] = WPDA_CSV_Uploads_Model::get_base_table_name();
36
37 parent::__construct( $args );
38
39 // Reset columns (we are in a sub page of the Data Explorer main page).
40 $this->wpda_list_columns = WPDA_List_Columns_Cache::get_list_columns(
41 $wpdb->dbname,
42 WPDA_CSV_Uploads_Model::get_base_table_name()
43 );
44 foreach ( $this->wpda_list_columns->get_table_columns() as $table_columns ) {
45 $this->columns_indexed[ $table_columns['column_name'] ] = $table_columns;
46 }
47 }
48
49 /**
50 * Show list table
51 *
52 * @return void
53 */
54 public function show() {
55 parent::show();
56
57 ?>
58 <script type="text/javascript">
59 jQuery(function() {
60 jQuery('#wpda_main_form').append('<input type="hidden" name="page_action" value="wpda_import_csv">');
61 });
62 </script>
63 <?php
64 }
65
66 /**
67 * Add mapping action link
68 *
69 * @param mixed $item Table columns.
70 * @param string $column_name Column name.
71 * @param string $actions Action.
72 * @return void
73 */
74 protected function column_default_add_action( $item, $column_name, &$actions ) {
75 // Add page_action to delete form.
76 ?>
77 <script type='text/javascript'>
78 jQuery("#delete_form_" + <?php echo esc_attr( self::$list_number - 1 ); ?>).attr('action', '?page=<?php echo esc_attr( $this->page ); ?>&page_action=wpda_import_csv');
79 </script>
80 <?php
81 // Add mapping form to actions.
82 $wp_nonce_action = "wpda-mapping-{$item['csv_id']}";
83 $wp_nonce = esc_attr( wp_create_nonce( $wp_nonce_action ) );
84 $form_id = '_' . ( self::$list_number - 1 );
85 $mapping_form = $this->create_post_form( 'mapping', "mapping_form{$form_id}", $item['csv_id'], $wp_nonce );
86 ?>
87 <script type='text/javascript'>
88 jQuery("#wpda_invisible_container").append("<?php echo $mapping_form; // phpcs:ignore WordPress.Security.EscapeOutput ?>");
89 </script>
90 <?php
91 $mapping =
92 sprintf(
93 '<a href="javascript:void(0)" class="view wpda_tooltip" title="' .
94 __( 'Map table and columns for CSV file: ', 'wp-data-access' ) . $item['csv_real_file_name'] .
95 '
96
97 Needs to be performed only once" onclick="jQuery(\'#mapping_form%s\').submit()">%s</a>',
98 $form_id,
99 'Mapping'
100 );
101
102 // Add import form to actions.
103 $wp_nonce_action = "wpda-import-csv-{$item['csv_id']}";
104 $wp_nonce = esc_attr( wp_create_nonce( $wp_nonce_action ) );
105 $import_form = $this->create_post_form( 'import_start', "import_form{$form_id}", $item['csv_id'], $wp_nonce, $item['csv_name'] );
106 ?>
107 <script type='text/javascript'>
108 jQuery("#wpda_invisible_container").append("<?php echo $import_form; // phpcs:ignore WordPress.Security.EscapeOutput ?>");
109 </script>
110 <?php
111 $import =
112 sprintf(
113 '<a href="javascript:void(0)" class="view wpda_tooltip" title="' .
114 __( 'Import CSV file: ', 'wp-data-access' ) . $item['csv_real_file_name'] .
115 '" onclick="jQuery(\'#import_form%s\').submit()">%s</a>',
116 $form_id,
117 'Import'
118 );
119
120 // Add reload form to actions.
121 $wp_nonce_action = "wpda-reload-csv-{$item['csv_id']}";
122 $wp_nonce = esc_attr( wp_create_nonce( $wp_nonce_action ) );
123 $reload_form = $this->create_post_form( 'reload', "reload_form{$form_id}", $item['csv_id'], $wp_nonce, $item['csv_name'], $item['csv_encoding'] );
124 ?>
125 <script type='text/javascript'>
126 jQuery("#wpda_invisible_container").append("<?php echo $reload_form; // phpcs:ignore WordPress.Security.EscapeOutput ?>");
127 </script>
128 <?php
129 $reload =
130 sprintf(
131 '<a href="javascript:void(0)" class="view wpda_tooltip" title="' .
132 __( 'Upload a newer version of CSV file: ', 'wp-data-access' ) . $item['csv_real_file_name'] .
133 '" onclick="jQuery(\'#reload_form%s\').submit()">%s</a>',
134 $form_id,
135 'Upload'
136 );
137
138 // Remove edit action.
139 unset( $actions['edit'] );
140
141 // Add new links to beginning of action list.
142 // phpcs:ignore -- 8.1 proof
143 $actions =
144 array_merge(
145 array( 'mapping' => $mapping ),
146 array( 'import' => $import ),
147 array( 'reload' => $reload ),
148 $actions
149 );
150 }
151
152 /**
153 * Create post form
154 *
155 * @param string $action Action.
156 * @param string $form_id Form ID.
157 * @param string $csv_id CSV ID.
158 * @param string $wpnonce Nonce.
159 * @param string $csv_name CSV internal name.
160 * @return array|string|string[]
161 */
162 private function create_post_form( $action, $form_id, $csv_id, $wpnonce, $csv_name = '', $csv_encoding = '' ) {
163 $esc_attr = 'esc_attr';
164
165 $csv_encoding_field = '';
166 if ( ! empty( $csv_encoding ) ) {
167 $csv_encoding_field = "<input type='hidden' name='csv_encoding' value='{$esc_attr( $csv_encoding )}' />";
168 }
169
170 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
171 $form = <<< EOT
172 <form id='{$esc_attr( $form_id )}' method='post'
173 action='?page={$esc_attr( $this->page )}&page_action=wpda_import_csv'
174 >
175 <input type='hidden' name='action' value='{$esc_attr( $action )}' />
176 <input type='hidden' name='csv_id' value='{$esc_attr( $csv_id )}' />
177 <input type='hidden' name='csv_name' value='{$esc_attr( $csv_name )}' />
178 {$csv_encoding_field}
179 <input type='hidden' name='_wpnonce' value='{$esc_attr( $wpnonce )}'>
180 </form>
181 EOT;
182 return str_replace( array( "\n", "\r" ), '', $form );
183 }
184
185 /**
186 * Get current bulk action
187 *
188 * @return array|mixed|string
189 */
190 public function get_bulk_actions() {
191 $actions = parent::get_bulk_actions();
192
193 if ( is_array( $actions ) ) {
194 unset( $actions['bulk-export'] );
195 unset( $actions['bulk-export-xml'] );
196 unset( $actions['bulk-export-json'] );
197 unset( $actions['bulk-export-excel'] );
198 unset( $actions['bulk-export-csv'] );
199 }
200
201 return $actions;
202 }
203
204 /**
205 * Process bulk action
206 *
207 * @return void
208 */
209 public function process_bulk_action() {
210 if ( 'delete' === $this->current_action() ) {
211 // Check if key is available.
212 if ( ! isset( $_REQUEST['csv_id'] ) ) { // input var okay.
213 wp_die( esc_html__( 'ERROR: Invalid URL [missing primary key values]', 'wp-data-access' ) );
214 }
215 $csv_id = sanitize_text_field( wp_unslash( $_REQUEST['csv_id'] ) ); // input var okay.
216
217 // Check if delete is allowed.
218 $wp_nonce_action = "wpda-delete-{$this->table_name}-{$csv_id}";
219 $wp_nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; // input var okay.
220 if ( ! wp_verify_nonce( $wp_nonce, $wp_nonce_action ) ) {
221 wp_die( esc_html__( 'ERROR: Not authorized', 'wp-data-access' ) );
222 }
223
224 // Delete CSV file and data.
225 $row = WPDA_CSV_Uploads_Model::query( $csv_id );
226 if ( is_array( $row ) && 1 === count( $row ) ) { // phpcs:ignore -- 8.1 proof
227 // Silently delete file.
228 if ( isset( $row[0]->csv_real_file_name ) ) {
229 unlink( WPDA::get_plugin_upload_dir() . $row[0]->csv_real_file_name ); // phpcs:ignore
230 }
231
232 // Delete record.
233 $next_row_to_be_deleted['csv_id'] = $csv_id;
234 if ( $this->delete_row( $next_row_to_be_deleted ) ) {
235 $msg = new WPDA_Message_Box(
236 array(
237 'message_text' => __( 'Row deleted', 'wp-data-access' ),
238 )
239 );
240 $msg->box();
241 } else {
242 $msg = new WPDA_Message_Box(
243 array(
244 'message_text' => __( 'Could not delete row', 'wp-data-access' ),
245 'message_type' => 'error',
246 'message_is_dismissible' => false,
247 )
248 );
249 $msg->box();
250 }
251 }
252 } elseif ( 'bulk-delete' === $this->current_action() ) {
253 if ( ! isset( $_REQUEST['bulk-selected'] ) ) { // input var okay.
254 $msg = new WPDA_Message_Box(
255 array(
256 'message_text' => __( 'Nothing to delete', 'wp-data-access' ),
257 )
258 );
259 $msg->box();
260
261 return;
262 }
263
264 // Check if delete is allowed.
265 $wp_nonce_action = "wpda-delete-{$this->table_name}";
266 $wp_nonce = isset( $_REQUEST['_wpnonce2'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce2'] ) ) : ''; // input var okay.
267 if ( ! wp_verify_nonce( $wp_nonce, $wp_nonce_action ) ) {
268 die( esc_html__( 'ERROR: Not authorized', 'wp-data-access' ) );
269 }
270
271 $bulk_rows = $_REQUEST['bulk-selected']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
272 // phpcs:ignore -- 8.1 proof
273 $no_rows = count( ( array ) $bulk_rows ); // # rows to be deleted.
274
275 $rows_to_be_deleted = array(); // Gonna hold rows to be deleted.
276 for ( $i = 0; $i < $no_rows; $i ++ ) {
277 // Write "json" to named array. Need to strip slashes twice. Once for the normal conversion
278 // and once extra for the pre-conversion of double quotes in method column_cb().
279 $row_object = json_decode( stripslashes( stripslashes( $bulk_rows[ $i ] ) ), true );
280
281 // Check if key is available.
282 if ( ! isset( $row_object['csv_id'] ) ) {
283 wp_die( esc_html__( 'ERROR: Invalid URL [missing primary key values]', 'wp-data-access' ) );
284 }
285
286 // Save key.
287 $rows_to_be_deleted[ $i ] = $row_object['csv_id'];
288 }
289
290 // Looks like everything is there. Delete records from table...
291 $rows_successfully_deleted = 0; // Number of rows successfully deleted.
292 $rows_with_errors = 0; // Number of rows that could not be deleted.
293 for ( $i = 0; $i < $no_rows; $i ++ ) {
294 // Delete CSV file and data.
295 $row = WPDA_CSV_Uploads_Model::query( $rows_to_be_deleted[ $i ] );
296 if ( is_array( $row ) && 1 === count( $row ) ) { // phpcs:ignore -- 8.1 proof
297 // Silently delete file.
298 if ( isset( $row[0]->csv_real_file_name ) ) {
299 unlink( WPDA::get_plugin_upload_dir() . $row[0]->csv_real_file_name ); // phpcs:ignore
300 }
301
302 // Delete record.
303 $next_row_to_be_deleted['csv_id'] = $rows_to_be_deleted[ $i ];
304 if ( $this->delete_row( $next_row_to_be_deleted ) ) {
305 $rows_successfully_deleted++;
306 } else {
307 $rows_with_errors++;
308 }
309 }
310 }
311
312 // Inform user about the results of the operation.
313 $message = '';
314
315 if ( 1 === $rows_successfully_deleted ) {
316 $message = __( 'CSV files deleted', 'wp-data-access' );
317 } elseif ( $rows_successfully_deleted > 1 ) {
318 $message = "$rows_successfully_deleted " . __( 'CSV files deleted', 'wp-data-access' );
319 }
320
321 if ( '' !== $message ) {
322 $msg = new WPDA_Message_Box(
323 array(
324 'message_text' => $message,
325 )
326 );
327 $msg->box();
328 }
329
330 $message = '';
331
332 if ( $rows_with_errors > 0 ) {
333 $message = __( 'Not all CSV files have been deleted', 'wp-data-access' );
334 }
335
336 if ( '' !== $message ) {
337 $msg = new WPDA_Message_Box(
338 array(
339 'message_text' => $message,
340 'message_type' => 'error',
341 'message_is_dismissible' => false,
342 )
343 );
344 $msg->box();
345 }
346 } else {
347 parent::process_bulk_action();
348 }
349 }
350
351 /**
352 * Get column labels
353 *
354 * @return array
355 */
356 public static function column_headers_labels() {
357 return array(
358 'csv_id' => __( 'ID', 'wp-data-access' ),
359 'csv_name' => __( 'Import Name', 'wp-data-access' ),
360 'csv_real_file_name' => __( 'Local file Name', 'wp-data-access' ),
361 'csv_orig_file_name' => __( 'File Name', 'wp-data-access' ),
362 'csv_timestamp' => __( 'Timestamp', 'wp-data-access' ),
363 'csv_mapping' => __( 'Mapping', 'wp-data-access' ),
364 'csv_encoding' => __( 'Encoding', 'wp-data-access' ),
365 );
366 }
367
368 }
369
370 }
371