| @@ -8,18 +8,14 @@ | ||
| 8 | 8 | // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- verified on page |
| 9 | 9 | namespace WPDataAccess\List_Table; |
| 10 | 10 | |
| 11 | 11 | use WPDataAccess\Connection\WPDADB; |
| 12 | -use WPDataAccess\Dashboard\WPDA_Dashboard; | |
| 13 | 12 | use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist; |
| 14 | -use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Lists; | |
| 15 | 13 | use WPDataAccess\Data_Dictionary\WPDA_List_Columns; |
| 16 | 14 | use WPDataAccess\Macro\WPDA_Macro; |
| 17 | 15 | use WPDataAccess\Plugin_Table_Models\WPDA_CSV_Uploads_Model; |
| 18 | 16 | use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model; |
| 19 | -use WPDataAccess\Utilities\WPDA_Import; | |
| 20 | 17 | use WPDataAccess\Utilities\WPDA_Message_Box; |
| 21 | -use WPDataAccess\Utilities\WPDA_Repository; | |
| 22 | 18 | use WPDataAccess\Wordpress_Original; |
| 23 | 19 | use WPDataAccess\WPDA; |
| 24 | 20 | use WPDataProjects\WPDP; |
| 25 | 21 | use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model; |
| @@ -210,15 +206,8 @@ | ||
| 210 | 206 | */ |
| 211 | 207 | protected $column_headers; |
| 212 | 208 | |
| 213 | 209 | /** |
| 214 | - * Reference to import object | |
| 215 | - * | |
| 216 | - * @var WPDA_Import | |
| 217 | - */ | |
| 218 | - protected $wpda_import = null; | |
| 219 | - | |
| 220 | - /** | |
| 221 | 210 | * Child tab clicked (used for parent child relationships only) |
| 222 | 211 | * |
| 223 | 212 | * @var null |
| 224 | 213 | */ |
| @@ -366,9 +355,9 @@ | ||
| 366 | 355 | * |
| 367 | 356 | * A list of rows for a specific table is based on WordPress class WP_List_Table. |
| 368 | 357 | * |
| 369 | 358 | * WPDA_List_Table can be used to build list tables for views as well. View based list tables however, do not |
| 370 | - * support insert, update, delete, import and export actions. | |
| 359 | + * support insert, update, delete and export actions. | |
| 371 | 360 | * |
| 372 | 361 | * A table name is not the only thing we need to build a list table. We also need to have access to the |
| 373 | 362 | * table columns. If no table columns are provided execution is stopped as well. |
| 374 | 363 | * |
| @@ -403,10 +392,8 @@ | ||
| 403 | 392 | * 'allow_update' => (string) on|off |
| 404 | 393 | * |
| 405 | 394 | * 'allow_delete' => (string) on|off |
| 406 | 395 | * |
| 407 | - * 'allow_import' => (string) on|off | |
| 408 | - * | |
| 409 | 396 | * 'hide_navigation' => (boolean) |
| 410 | 397 | * |
| 411 | 398 | * 'default_where' => (string) |
| 412 | 399 | * |
| @@ -479,17 +466,8 @@ | ||
| 479 | 466 | } elseif ( WPDA::is_wpda_table( $this->table_name ) ) { |
| 480 | 467 | $this->subtitle = '<span class="dashicons dashicons-warning"></span> ' . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WPDA ); |
| 481 | 468 | } |
| 482 | 469 | } |
| 483 | - if ( !(isset( $args['allow_import'] ) && 'off' === $args['allow_import']) ) { | |
| 484 | - try { | |
| 485 | - // Instantiate WPDA_Import. | |
| 486 | - $this->wpda_import = new WPDA_Import(( is_admin() ? "?page={$this->page}" : '' ), $this->schema_name, $this->table_name); | |
| 487 | - } catch ( \Exception $e ) { | |
| 488 | - // If import is turned off instantiation will fail. Handle is set to null (check in future calls). | |
| 489 | - $this->wpda_import = null; | |
| 490 | - } | |
| 491 | - } | |
| 492 | 470 | if ( isset( $args['bulk_export_enabled'] ) ) { |
| 493 | 471 | $this->bulk_export_enabled = $args['bulk_export_enabled']; |
| 494 | 472 | } |
| 495 | 473 | if ( isset( $args['search_box_enabled'] ) ) { |
| @@ -546,14 +524,14 @@ | ||
| 546 | 524 | // Get page number(s). |
| 547 | 525 | if ( 'page_number' !== $this->page_number_item_name ) { |
| 548 | 526 | if ( isset( $_REQUEST['page_number'] ) ) { |
| 549 | 527 | $requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST['page_number'] ) ); |
| 550 | - $this->page_number_link = '&page_number=' . $requested_page_number; | |
| 551 | - $this->page_number_item = "<input type='hidden' name='page_number' value='" . $requested_page_number . "' />"; | |
| 528 | + $this->page_number_link = '&page_number=' . esc_attr( $requested_page_number ); | |
| 529 | + $this->page_number_item = "<input type='hidden' name='page_number' value='" . esc_attr( $requested_page_number ) . "' />"; | |
| 552 | 530 | } |
| 553 | 531 | } |
| 554 | - $this->page_number_link .= '&paged=' . $this->get_pagenum(); | |
| 555 | - $this->page_number_item .= "<input type='hidden' name='" . esc_attr( $this->page_number_item_name ) . "' value='" . $this->get_pagenum() . "' />"; | |
| 532 | + $this->page_number_link .= '&paged=' . esc_attr( $this->get_pagenum() ); | |
| 533 | + $this->page_number_item .= "<input type='hidden' name='" . esc_attr( $this->page_number_item_name ) . "' value='" . esc_attr( $this->get_pagenum() ) . "' />"; | |
| 556 | 534 | // Add search arguments to link to return to same page. |
| 557 | 535 | foreach ( $_REQUEST as $key => $value ) { |
| 558 | 536 | if ( substr( $key, 0, 19 ) === 'wpda_search_column_' && count( array_filter( $this->wpda_list_columns->get_table_columns(), function ( $column ) use($key) { |
| 559 | 537 | return $column['column_name'] === substr( $key, 19 ); |
| @@ -958,9 +936,15 @@ | ||
| 958 | 936 | } else { |
| 959 | 937 | $hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' ); |
| 960 | 938 | $hyperlink_target = ( isset( $hyperlink->hyperlink_target ) ? $hyperlink->hyperlink_target : false ); |
| 961 | 939 | $target = ( true === $hyperlink_target ? "target='_blank'" : '' ); |
| 962 | - return "<a href='" . str_replace( ' ', '+', trim( $hyperlink_html ) ) . "' {$target}>{$hyperlink_label}</a>"; | |
| 940 | + if ( false === $hyperlink_target ) { | |
| 941 | + $json = json_decode( $hyperlink_html, true ); | |
| 942 | + if ( isset( $json['url'] ) ) { | |
| 943 | + $hyperlink_target = $json['url']; | |
| 944 | + } | |
| 945 | + } | |
| 946 | + return "<a href='" . esc_url_raw( $hyperlink_target ) . "' {$target}>" . esc_attr( $hyperlink_label ) . "</a>"; | |
| 963 | 947 | } |
| 964 | 948 | } else { |
| 965 | 949 | return ''; |
| 966 | 950 | } |
| @@ -977,14 +961,14 @@ | ||
| 977 | 961 | $url = wp_get_attachment_url( esc_attr( $image_id ) ); |
| 978 | 962 | if ( false !== $url ) { |
| 979 | 963 | $title = get_the_title( esc_attr( $image_id ) ); |
| 980 | 964 | $image_src .= ( '' !== $image_src ? '<br/>' : '' ); |
| 981 | - $image_src .= sprintf( '<img src="%s" class="wpda_tooltip" title="%s" width="100%%">', $url, $title ); | |
| 965 | + $image_src .= sprintf( '<img src="%s" class="wpda_tooltip" title="%s" width="100%%">', esc_url( $url ), esc_attr( $title ) ); | |
| 982 | 966 | } |
| 983 | 967 | } |
| 984 | 968 | return $image_src; |
| 985 | 969 | } elseif ( 'ImageURL' === $media_type ) { |
| 986 | - return sprintf( '<img src="%s" class="wpda_tooltip" width="100%%">', $item[$column_name] ); | |
| 970 | + return sprintf( '<img src="%s" class="wpda_tooltip" width="100%%">', esc_url( $item[$column_name] ) ); | |
| 987 | 971 | } elseif ( 'Attachment' === $media_type ) { |
| 988 | 972 | $media_ids = explode( ',', (string) $item[$column_name] ); |
| 989 | 973 | // phpcs:ignore -- 8.1 proof |
| 990 | 974 | $media_links = ''; |
| @@ -1008,9 +992,9 @@ | ||
| 1008 | 992 | if ( is_array( $hyperlink ) && isset( $hyperlink['label'] ) && isset( $hyperlink['url'] ) && isset( $hyperlink['target'] ) ) { |
| 1009 | 993 | if ( '' === $hyperlink['url'] ) { |
| 1010 | 994 | return ''; |
| 1011 | 995 | } else { |
| 1012 | - return "<a href='{$hyperlink['url']}' target='{$hyperlink['target']}'>{$hyperlink['label']}</a>"; | |
| 996 | + return "<a href='" . esc_url_raw( $hyperlink['url'] ) . "' target='" . esc_attr( $hyperlink['target'] ) . "'>" . esc_attr( $hyperlink['label'] ) . "</a>"; | |
| 1013 | 997 | } |
| 1014 | 998 | } else { |
| 1015 | 999 | return ''; |
| 1016 | 1000 | } |
| @@ -1015,9 +999,9 @@ | ||
| 1015 | 999 | return ''; |
| 1016 | 1000 | } |
| 1017 | 1001 | } else { |
| 1018 | 1002 | $hyperlink_label = $this->wpda_list_columns->get_column_label( $column_name ); |
| 1019 | - return "<a href='{$item[$column_name]}' target='_blank'>{$hyperlink_label}</a>"; | |
| 1003 | + return "<a href='" . esc_url_raw( $item[$column_name] ) . "' target='_blank'>" . esc_attr( $hyperlink_label ) . "</a>"; | |
| 1020 | 1004 | } |
| 1021 | 1005 | } |
| 1022 | 1006 | } elseif ( 'Audio' === $media_type ) { |
| 1023 | 1007 | $audio_ids = explode( ',', (string) $item[$column_name] ); |
| @@ -1028,9 +1012,9 @@ | ||
| 1028 | 1012 | $url = wp_get_attachment_url( esc_attr( $audio_id ) ); |
| 1029 | 1013 | if ( false !== $url ) { |
| 1030 | 1014 | $title = get_the_title( esc_attr( $audio_id ) ); |
| 1031 | 1015 | if ( false !== $url ) { |
| 1032 | - $audio_src .= '<div title="' . $title . '" class="wpda_tooltip">' . do_shortcode( '[audio src="' . $url . '"]' ) . '</div>'; | |
| 1016 | + $audio_src .= '<div title="' . esc_attr( $title ) . '" class="wpda_tooltip">' . do_shortcode( '[audio src="' . esc_url_raw( $url ) . '"]' ) . '</div>'; | |
| 1033 | 1017 | } |
| 1034 | 1018 | } |
| 1035 | 1019 | } |
| 1036 | 1020 | } |
| @@ -1043,9 +1027,9 @@ | ||
| 1043 | 1027 | if ( 'video' === substr( get_post_mime_type( $video_id ), 0, 5 ) ) { |
| 1044 | 1028 | $url = wp_get_attachment_url( esc_attr( $video_id ) ); |
| 1045 | 1029 | if ( false !== $url ) { |
| 1046 | 1030 | if ( false !== $url ) { |
| 1047 | - $video_src .= do_shortcode( '[video src="' . $url . '"]' ); | |
| 1031 | + $video_src .= do_shortcode( '[video src="' . esc_url_raw( $url ) . '"]' ); | |
| 1048 | 1032 | } |
| 1049 | 1033 | } |
| 1050 | 1034 | } |
| 1051 | 1035 | } |
| @@ -1122,11 +1106,11 @@ | ||
| 1122 | 1106 | \t\t\t\t\t{$add_parent_args_as_string} |
| 1123 | 1107 | \t\t\t\t\t{$add_schema_and_table_name} |
| 1124 | 1108 | \t\t\t\t\t<input type='hidden' name='action' value='{$esc_attr( $action )}' /> |
| 1125 | 1109 | \t\t\t\t\t<input type='hidden' name='_wpnonce' value='{$esc_attr( $wp_nonce )}'> |
| 1126 | -\t\t\t\t\t{$row_security_nonce_field} | |
| 1127 | -\t\t\t\t\t{$page_number_item} | |
| 1128 | -\t\t\t\t\t{$case_sensitive_search} | |
| 1110 | +\t\t\t\t\t{$esc_attr( $row_security_nonce_field )} | |
| 1111 | +\t\t\t\t\t{$esc_attr( $page_number_item )} | |
| 1112 | +\t\t\t\t\t{$esc_attr( $case_sensitive_search )} | |
| 1129 | 1113 | \t\t\t\t</form> |
| 1130 | 1114 | EOT; |
| 1131 | 1115 | return str_replace( array("\n", "\r"), '', $form ); |
| 1132 | 1116 | } |
| @@ -1153,11 +1137,11 @@ | ||
| 1153 | 1137 | $class = 'dashicons-external'; |
| 1154 | 1138 | } |
| 1155 | 1139 | return sprintf( |
| 1156 | 1140 | '<a href="%s" title="%s" target="_blank"><span class="dashicons %s wpda_attachment_icon"></span></a>', |
| 1157 | - $url, | |
| 1158 | - $title, | |
| 1159 | - $class | |
| 1141 | + esc_url( $url ), | |
| 1142 | + esc_attr( $title ), | |
| 1143 | + esc_attr( $class ) | |
| 1160 | 1144 | ); |
| 1161 | 1145 | } |
| 1162 | 1146 | |
| 1163 | 1147 | /** |
| @@ -1191,11 +1175,11 @@ | ||
| 1191 | 1175 | __( 'Output limited to %1$s characters', 'wp-data-access' ), |
| 1192 | 1176 | WPDA::get_option( WPDA::OPTION_BE_TEXT_WRAP ) |
| 1193 | 1177 | ); |
| 1194 | 1178 | if ( $substitute_newlines ) { |
| 1195 | - return str_replace( "\n", '<br/>', substr( esc_html( str_replace( '&', '&', (string) $column_content ) ), 0, WPDA::get_option( WPDA::OPTION_BE_TEXT_WRAP ) ) . ' <a href="javascript:void(0)" title="' . $title . '">•••</a>' ); | |
| 1179 | + return str_replace( "\n", '<br/>', substr( esc_html( str_replace( '&', '&', (string) $column_content ) ), 0, WPDA::get_option( WPDA::OPTION_BE_TEXT_WRAP ) ) . ' <a href="javascript:void(0)" title="' . esc_attr( $title ) . '">•••</a>' ); | |
| 1196 | 1180 | } else { |
| 1197 | - return substr( esc_html( str_replace( '&', '&', (string) $column_content ) ), 0, WPDA::get_option( WPDA::OPTION_BE_TEXT_WRAP ) ) . ' <a href="javascript:void(0)" title="' . $title . '">•••</a>'; | |
| 1181 | + return substr( esc_html( str_replace( '&', '&', (string) $column_content ) ), 0, WPDA::get_option( WPDA::OPTION_BE_TEXT_WRAP ) ) . ' <a href="javascript:void(0)" title="' . esc_attr( $title ) . '">•••</a>'; | |
| 1198 | 1182 | } |
| 1199 | 1183 | } else { |
| 1200 | 1184 | $column_data_type = $this->wpda_list_columns->get_column_data_type( $column_name ); |
| 1201 | 1185 | switch ( $column_data_type ) { |
| @@ -1343,12 +1327,8 @@ | ||
| 1343 | 1327 | * |
| 1344 | 1328 | * @see WPDA_List_Table::display() |
| 1345 | 1329 | */ |
| 1346 | 1330 | public function show() { |
| 1347 | - // Check for import requested. | |
| 1348 | - if ( null !== $this->wpda_import ) { | |
| 1349 | - $this->wpda_import->check_post(); | |
| 1350 | - } | |
| 1351 | 1331 | // Prepare list table items. |
| 1352 | 1332 | $this->prepare_items(); |
| 1353 | 1333 | // Show list table. |
| 1354 | 1334 | ?> |
| @@ -1422,12 +1402,8 @@ | ||
| 1422 | 1402 | <input type="text" name="_wpnonce" id="wpda_row_export_form__wpnonce" /> |
| 1423 | 1403 | </form> |
| 1424 | 1404 | </div> |
| 1425 | 1405 | <?php |
| 1426 | - // Add import container. | |
| 1427 | - if ( null !== $this->wpda_import ) { | |
| 1428 | - $this->wpda_import->add_container(); | |
| 1429 | - } | |
| 1430 | 1406 | // Add custom code before the list table. |
| 1431 | 1407 | do_action_ref_array( 'wpda_before_list_table', array($this) ); |
| 1432 | 1408 | // Prepare url. |
| 1433 | 1409 | if ( is_admin() ) { |
| @@ -1588,19 +1564,15 @@ | ||
| 1588 | 1564 | |
| 1589 | 1565 | /** |
| 1590 | 1566 | * Add button to page header |
| 1591 | 1567 | * |
| 1592 | - * By default "add new" and "import" buttons are added (depending on the settings). Overwrite this method to | |
| 1568 | + * "Add new" button is added (depending on the settings). Overwrite this method to | |
| 1593 | 1569 | * add your own buttons. |
| 1594 | 1570 | * |
| 1595 | 1571 | * @since 1.0.1 |
| 1596 | 1572 | */ |
| 1597 | 1573 | protected function add_header_button() { |
| 1598 | - if ( 'off' === $this->allow_insert ) { | |
| 1599 | - if ( null !== $this->wpda_import ) { | |
| 1600 | - $this->wpda_import->add_button(); | |
| 1601 | - } | |
| 1602 | - } else { | |
| 1574 | + if ( 'off' !== $this->allow_insert ) { | |
| 1603 | 1575 | // phpcs:ignore -- 8.1 proof |
| 1604 | 1576 | if ( WPDA::is_wpda_table( $this->table_name ) || ('on' === WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) && count( $this->wpda_list_columns->get_table_primary_key() )) > 0 ) { |
| 1605 | 1577 | $storage_type = ( WPDA::is_wpda_table( $this->table_name ) ? __( 'respository', 'wp-data-access' ) : __( 'table', 'wp-data-access' ) ); |
| 1606 | 1578 | // Prepare url. |
| @@ -1639,22 +1611,11 @@ | ||
| 1639 | 1611 | <?php |
| 1640 | 1612 | echo esc_attr__( 'Add New', 'wp-data-access' ); |
| 1641 | 1613 | ?> |
| 1642 | 1614 | </button> |
| 1643 | - <?php | |
| 1644 | - // Add import button to title. | |
| 1645 | - if ( null !== $this->wpda_import ) { | |
| 1646 | - $this->wpda_import->add_button(); | |
| 1647 | - } | |
| 1648 | - ?> | |
| 1649 | 1615 | </div> |
| 1650 | 1616 | </form> |
| 1651 | 1617 | <?php |
| 1652 | - } else { | |
| 1653 | - // Add import button to title. | |
| 1654 | - if ( null !== $this->wpda_import ) { | |
| 1655 | - $this->wpda_import->add_button(); | |
| 1656 | - } | |
| 1657 | 1618 | } |
| 1658 | 1619 | } |
| 1659 | 1620 | } |
| 1660 | 1621 | |
| @@ -2213,9 +2174,9 @@ | ||
| 2213 | 2174 | $columns = $this->get_sortable_columns(); |
| 2214 | 2175 | // Check column name for SQL injection. |
| 2215 | 2176 | if ( isset( $columns[$orderby_arg] ) || $this->wpda_data_dictionary->column_exists( $orderby_arg ) ) { |
| 2216 | 2177 | // Column name exists in current table, safely continue... |
| 2217 | - $orderby = " order by {$orderby_arg}"; | |
| 2178 | + $orderby = ' order by `' . WPDA::remove_backticks( $orderby_arg ) . '`'; | |
| 2218 | 2179 | // Prevent SQL injection for order. If 'desc' is found result will be ordered desc. In all other |
| 2219 | 2180 | // cases we'll order asc. |
| 2220 | 2181 | $orderby .= ( strtolower( trim( $order_arg ) ) === 'desc' ? ' desc' : ' asc' ); |
| 2221 | 2182 | return $orderby; |
| @@ -2625,8 +2586,11 @@ | ||
| 2625 | 2586 | * Add full export to CSV and JSON buttons |
| 2626 | 2587 | * Needs to be granted in project page configuration |
| 2627 | 2588 | */ |
| 2628 | 2589 | protected function add_full_table_downloads() { |
| 2590 | + if ( !WPDA::current_user_is_admin() ) { | |
| 2591 | + return; | |
| 2592 | + } | |
| 2629 | 2593 | } |
| 2630 | 2594 | |
| 2631 | 2595 | // Override to add arguments to CSV and JSON full table exports. |
| 2632 | 2596 | protected function add_full_table_downloads_add_args() { |