* @package WP OAuth Server
*/
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
class WO_Table extends WP_List_Table {
/**
* Constructor, we override the parent to pass our own arguments
* We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
*/
public function __construct() {
parent::__construct(
array(
'singular' => 'wp_list_text_link', // Singular label
'plural' => 'wp_list_test_links', // plural label, also this well be one of the table css class
'ajax' => false, // We won't support Ajax for this table
)
);
}
/**
* Add extra markup in the toolbars before or after the list.
*
* @param string $which , helps you decide if you add the markup after (bottom) or before (top) the list
*/
public function extra_tablenav( $which ) {
if ( $which == 'top' ) {
return false;
}
if ( $which == 'bottom' ) {
return false;
}
}
/**
* Overide default functionality to remove _nonce field.
*
* @return [type] [description]
*/
public function display_tablenav( $which ) {
?>
bulk_actions( $which );
?>
extra_tablenav( $which );
$this->pagination( $which );
?>
__( 'Name' ),
'client_id' => __( 'Client ID' ),
// 'client_secret' => __( 'Redirect URI' )
);
}
/**
* Decide which columns to activate the sorting functionality on.
*
* @return array $sortable, the array of columns that can be sorted by the user
*/
public function get_sortable_columns() {
return $sortable = array(
// 'name' => array('name'),
// 'user_id'=>array('user_id')
);
}
/**
* Prepare the table with different parameters, pagination, columns and table elements.
*
* @Updated 4.0.2. does not include user generated clients anymore via original query
*/
public function prepare_items() {
global $wpdb, $_wp_column_headers;
$screen = get_current_screen();
// 🔐 SECURITY FIX: Use prepared statements to prevent SQL injection
$query = $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts WHERE post_type = %s AND post_name NOT LIKE %s",
'wo_client',
'user_generated_%'
);
$totalitems = $wpdb->query( $query );
$perpage = 5;
// 🔐 SECURITY FIX: Validate pagination to prevent DoS attacks
$paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
$paged = max(1, min(1000, $paged)); // Limit between 1-1000 pages
$totalpages = ceil( $totalitems / $perpage );
$this->set_pagination_args(
array(
'total_items' => $totalitems,
'total_pages' => $totalpages,
'per_page' => $perpage,
)
);
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$results = $wpdb->get_results( $query );
$this->items = $results;
}
/**
* Display the rows of records in the table.
*
* @return string, echo the markup of the rows
*/
public function display_rows() {
// Get the records registered in the prepare_items method
$records = $this->items;
// Get the columns registered in the get_columns and get_sortable_columns methods
list( $columns, $hidden ) = $this->get_column_info();
// Loop for each record
if ( ! empty( $records ) ) {
foreach ( $records as $rec ) {
// Open the line
echo '';
foreach ( $columns as $column_name => $column_display_name ) {
// Style attributes for each col
$class = "class='$column_name column-$column_name'";
$style = '';
if ( in_array( $column_name, $hidden ) ) {
$style = ' style="display:none;"';
}
$attributes = $class . $style;
switch ( $column_name ) {
case 'title':
$edit_link = admin_url( 'admin.php?page=wo_edit_client&id=' . $rec->ID );
echo '| ' . esc_html( $rec->post_title ) . '
|
';
}
}
}
}