diff --git a/includes/admin/class-geodir-admin-report-post-list-table.php b/includes/admin/class-geodir-admin-report-post-list-table.php index 238cf012..e4f5fcdc 100644 --- a/includes/admin/class-geodir-admin-report-post-list-table.php +++ b/includes/admin/class-geodir-admin-report-post-list-table.php @@ -35,7 +35,7 @@ public function __construct( $args = array() ) { array( 'plural' => 'report-posts', 'singular' => 'report-post', - 'ajax' => true + 'ajax' => true, ) ); } @@ -67,10 +67,10 @@ public function get_columns() { */ protected function get_sortable_columns() { $sortable_columns = array( - 'post_title' => array( 'post_title', false ), + 'post_title' => array( 'post_title', false ), 'post_author' => array( 'post_author', false ), - 'post_date' => array( 'post_date', true ), - 'user_name' => array( 'user_name', false ), + 'post_date' => array( 'post_date', true ), + 'user_name' => array( 'user_name', false ), 'report_date' => array( 'report_date', true ), ); return $sortable_columns; @@ -87,24 +87,37 @@ public function prepare_items() { $table = GEODIR_POST_REPORTS_TABLE; - $status = isset( $_REQUEST['status'] ) ? sanitize_text_field( $_REQUEST['status'] ) : 'pending'; + $nonce = ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : ''; + + if ( ! empty( $nonce ) && ! check_admin_referer( 'bulk-' . $this->_args['plural'] ) ) { + wp_die(); + } + + $status = isset( $_REQUEST['status'] ) ? sanitize_text_field( $_REQUEST['status'] ) : 'pending'; if ( ! in_array( $status, array( 'all', 'resolved', 'pending', 'rejected' ), true ) ) { $status = 'pending'; } - $reason = ! empty( $_REQUEST['reason'] ) ? sanitize_text_field( $_REQUEST['reason'] ) : ''; - $search = ( isset( $_REQUEST['s'] ) ) ? sanitize_text_field( $_REQUEST['s'] ) : ''; - $reason = ( isset( $_REQUEST['reason'] ) ) ? sanitize_text_field( $_REQUEST['reason'] ) : ''; + $allowed_orderby = array( + 'post_title', + 'post_author', + 'post_date', + 'user_name', + 'report_date', + ); + + $reason = ! empty( $_REQUEST['reason'] ) ? sanitize_text_field( $_REQUEST['reason'] ) : ''; + $search = ( isset( $_REQUEST['s'] ) ) ? sanitize_text_field( $_REQUEST['s'] ) : ''; $user_id = ( isset( $_REQUEST['user_id'] ) ) ? absint( $_REQUEST['user_id'] ) : ''; - $orderby = ( isset( $_REQUEST['orderby'] ) ) ? esc_sql( $_REQUEST['orderby'] ) : 'report_date'; - $order = ( isset( $_REQUEST['order'] ) ) ? esc_sql( $_REQUEST['order'] ) : 'DESC'; + $orderby = ( isset( $_REQUEST['orderby'] ) && in_array( $_REQUEST['orderby'], $allowed_orderby, true ) ) ? sanitize_sql_orderby( $_REQUEST['orderby'] ) : 'report_date'; + $order = ( isset( $_REQUEST['order'] ) && 'ASC' === $_REQUEST['order'] ) ? 'ASC' : 'DESC'; $reports_per_page = $this->get_per_page( $status ); $doing_ajax = wp_doing_ajax(); $number = ! empty( $_REQUEST['number'] ) ? absint( $_REQUEST['number'] ) : $reports_per_page; - $page = $this->get_pagenum(); + $page = $this->get_pagenum(); if ( isset( $_REQUEST['start'] ) ) { $start = absint( $_REQUEST['start'] ); @@ -117,16 +130,16 @@ public function prepare_items() { } $args = array( - 'status' => $status, - 'search' => $search, - 'user_id' => $user_id, - 'offset' => $start, - 'number' => $number, - 'post_id' => $post_id, - 'type' => $reason, - 'orderby' => $orderby, - 'order' => $order, - 'reason' => $reason, + 'status' => $status, + 'search' => $search, + 'user_id' => $user_id, + 'offset' => $start, + 'number' => $number, + 'post_id' => $post_id, + 'type' => $reason, + 'orderby' => $orderby, + 'order' => $order, + 'reason' => $reason, ); /** @@ -138,45 +151,45 @@ public function prepare_items() { */ $args = apply_filters( 'geodir_admin_post_reports_list_table_query_args', $args ); - $where = ""; + $where = ''; // post_id if ( ! empty( $args['post_id'] ) ) { - $where .= $wpdb->prepare( " AND r.post_id = %d", array( absint( $args['post_id'] ) ) ); + $where .= $wpdb->prepare( ' AND r.post_id = %d', array( absint( $args['post_id'] ) ) ); } // status - if ( ! empty( $args['status'] ) && $args['status'] != 'all' ) { - if ( $args['status'] == 'pending' ) { + if ( ! empty( $args['status'] ) && 'all' !== $args['status'] ) { + if ( 'pending' === $args['status'] ) { $args['status'] = ''; } - $where .= $wpdb->prepare( " AND r.status = %s", array( $args['status'] ) ); + $where .= $wpdb->prepare( ' AND r.status = %s', array( $args['status'] ) ); } // reason if ( ! empty( $args['reason'] ) ) { - $where .= $wpdb->prepare( " AND r.reason LIKE %s", array( $args['reason'] ) ); + $where .= $wpdb->prepare( ' AND r.reason LIKE %s', array( $args['reason'] ) ); } if ( ! empty( $args['search'] ) ) { if ( is_email( $args['search'] ) ) { - $where .= $wpdb->prepare( " AND r.user_email LIKE %s", array( $args['search'] ) ); + $where .= $wpdb->prepare( ' AND r.user_email LIKE %s', array( $args['search'] ) ); } else { $keyword = '%' . $wpdb->esc_like( $args['search'] ) . '%'; - $where .= $wpdb->prepare( " AND ( r.user_ip = %s OR r.user_name LIKE %s OR p.post_title LIKE %s OR r.user_email LIKE %s OR r.message LIKE %s )", array( $args['search'], $keyword, $keyword, $keyword, $keyword ) ); + $where .= $wpdb->prepare( ' AND ( r.user_ip = %s OR r.user_name LIKE %s OR p.post_title LIKE %s OR r.user_email LIKE %s OR r.message LIKE %s )', array( $args['search'], $keyword, $keyword, $keyword, $keyword ) ); } } - $count_sql = "SELECT COUNT(*)"; - $sql = "SELECT p.post_title, p.post_author, p.post_status, p.post_date, r.*"; - $commmon_sql = "FROM {$table} AS r LEFT JOIN {$wpdb->posts} AS p ON p.ID = r.post_id WHERE p.ID IS NOT NULL {$where}"; - $total_items = $wpdb->get_var( "SELECT COUNT(*) {$commmon_sql}" ); + $total_items = $wpdb->get_var( "SELECT COUNT(*) {$commmon_sql}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $common_sql uses prepare above. + - $_orderby = ! empty( $orderby ) && ! empty( $order ) ? "ORDER BY {$orderby} {$order}" : ''; - $_limit = $wpdb->prepare( "LIMIT %d, %d", array( $args['offset'], $args['number'] ) ); + $_orderby = ! empty( $orderby ) ? "ORDER BY {$orderby} {$order}" : ''; + $_orderby = sanitize_sql_orderby( $_orderby ) ? sanitize_sql_orderby( $_orderby ) : 'ORDER BY report_date DESC'; - $this->items = $wpdb->get_results( "SELECT p.post_title, p.post_author, p.post_status, p.post_date, r.* {$commmon_sql} {$_orderby} {$_limit}" ); + $_limit = $wpdb->prepare( 'LIMIT %d, %d', array( $args['offset'], $args['number'] ) ); + + $this->items = $wpdb->get_results( "SELECT p.post_title, p.post_author, p.post_status, p.post_date, r.* {$commmon_sql} {$_orderby} {$_limit}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- All items secure. $this->set_pagination_args( array( @@ -195,7 +208,7 @@ public function process_bulk_action() { global $wpdb; $doaction = $this->current_action(); - + if ( ! $doaction || ! current_user_can( 'manage_options' ) ) { return; } @@ -211,10 +224,10 @@ public function process_bulk_action() { $resolved = 0; $rejected = 0; $deleted_ = 0; - $pending = 0; - $draft = 0; - $trash = 0; - $deleted = 0; + $pending = 0; + $draft = 0; + $trash = 0; + $deleted = 0; $pagenum = $this->get_pagenum(); @@ -313,14 +326,14 @@ protected function get_views() { global $post_id, $status, $reason; $status_links = array(); - $post_id = ! empty( $post_id ) ? absint( $post_id ) : 0; - $num_reports = GeoDir_Report_Post::get_counts( $post_id ); + $post_id = ! empty( $post_id ) ? absint( $post_id ) : 0; + $num_reports = GeoDir_Report_Post::get_counts( $post_id ); if ( empty( $status ) ) { $status = 'all'; } $stati = array( - 'all' => _nx_noop( + 'all' => _nx_noop( 'All (%s)', 'All (%s)', 'reported posts', @@ -332,7 +345,7 @@ protected function get_views() { 'reported posts', 'geodirectory' ), - 'resolved' => _nx_noop( + 'resolved' => _nx_noop( 'Resolved (%s)', 'Resolved (%s)', 'reported posts', @@ -343,7 +356,7 @@ protected function get_views() { 'Rejected (%s)', 'reported posts', 'geodirectory' - ) + ), ); $link = admin_url( 'admin.php?page=gd-settings&tab=general§ion=report_post' ); @@ -377,7 +390,9 @@ protected function get_views() { $link = add_query_arg( 'p', absint( $post_id ), $link ); } - $status_links[ $_status ] = "" . wp_sprintf( translate_nooped_plural( $label, $num_reports->{$_status} ), wp_sprintf( '%s', 'pending', number_format_i18n( $num_reports->{$_status} ) ) + $status_links[ $_status ] = "" . wp_sprintf( + translate_nooped_plural( $label, $num_reports->{$_status} ), + wp_sprintf( '%s', 'pending', number_format_i18n( $num_reports->{$_status} ) ) ) . ''; } @@ -393,13 +408,13 @@ protected function get_bulk_actions() { global $status; $actions = array( - 'pending' => __( 'Unpublish', 'geodirectory' ), - 'draft' => __( 'Move to Draft', 'geodirectory' ), - 'trash' => __( 'Move to Trash', 'geodirectory' ), - 'delete' => __( 'Delete Permanently', 'geodirectory' ), - 'resolved' => __( 'Mark as Resolved', 'geodirectory' ), - 'rejected' => __( 'Mark as Rejected', 'geodirectory' ), - 'delete-reports' => __( 'Delete Reports', 'geodirectory' ) + 'pending' => __( 'Unpublish', 'geodirectory' ), + 'draft' => __( 'Move to Draft', 'geodirectory' ), + 'trash' => __( 'Move to Trash', 'geodirectory' ), + 'delete' => __( 'Delete Permanently', 'geodirectory' ), + 'resolved' => __( 'Mark as Resolved', 'geodirectory' ), + 'rejected' => __( 'Mark as Rejected', 'geodirectory' ), + 'delete-reports' => __( 'Delete Reports', 'geodirectory' ), ); return $actions; @@ -538,7 +553,7 @@ public function display() { items; + $items = $this->items; $this->display_rows_or_placeholder(); $this->items = $items; ?> @@ -659,13 +674,13 @@ protected function handle_row_actions( $item, $column_name, $primary ) { $out = ''; $actions = array( - 'id' => '', + 'id' => '', 'view' => '', ); // Not looking at all comments. if ( $post->post_status != 'trash' ) { - $actions['id'] = wp_sprintf( __( 'ID: %s', 'geodirectory' ), $post->ID ); + $actions['id'] = wp_sprintf( __( 'ID: %s', 'geodirectory' ), $post->ID ); $actions['view'] = wp_sprintf( '%s', get_permalink( $post->ID ), esc_attr( wp_sprintf( __( 'View “%s”', 'geodirectory' ), _draft_or_post_title( (int) $post->ID ) ) ), wp_sprintf( __( 'View %s', 'geodirectory' ), geodir_post_type_singular_name( $post->post_type, true ) ) ); } @@ -707,8 +722,8 @@ public function column_cb( $item ) { } public function column_post_title( $item ) { - $title = _draft_or_post_title( (int) $item->post_id ); - $post = get_post( (int) $item->post_id ); + $title = _draft_or_post_title( (int) $item->post_id ); + $post = get_post( (int) $item->post_id ); $can_edit_post = current_user_can( 'edit_post', $post->ID ); $value = ''; @@ -716,7 +731,7 @@ public function column_post_title( $item ) { if ( $can_edit_post && 'trash' !== $post->post_status ) { $value .= wp_sprintf( '%s', get_edit_post_link( $post->ID ), esc_attr( sprintf( __( '“%s” (Edit)', 'geodirectory' ), $title ) ), $title ); } else { - $value .=wp_sprintf( '%s', $title ); + $value .= wp_sprintf( '%s', $title ); } $value .= "\n"; @@ -731,7 +746,7 @@ public function column_post_author( $item ) { if ( current_user_can( 'edit_user', $post->post_author ) ) { $edit_link = get_edit_user_link( $post->post_author ); - $value = "{$label}"; + $value = "{$label}"; } else { $value = "{$label}"; } @@ -780,7 +795,7 @@ public function column_user_name( $item ) { if ( ! empty( $item->user_id ) && current_user_can( 'edit_user', (int) $item->user_id ) ) { $edit_link = get_edit_user_link( (int) $item->user_id ); - $value = "{$label}
"; + $value = "{$label}
"; } else { $value = "{$label}
"; } diff --git a/readme.txt b/readme.txt index 37709c3f..d37a33a5 100644 --- a/readme.txt +++ b/readme.txt @@ -291,6 +291,7 @@ __WARNING: GDv2 is a significant update over GDv1 and may require manual work, s * Elementor Pro Gallery not working with single gallery type - FIXED * GD Details page admin hints don't show link from CPT template settings - FIXED * Allow to customize add listing map via theme template - CHANGED +* Admin users had the ability to alter the report posts table orderby SQL - FIXED/SECURITY = GeoDirectory Business Directory Plugin v2.3.28 - 2023-10-13 = * Add / Edit CPT package shows error on update plugin - FIXED