",
'',
$current,
strlen( $total_pages )
);
}
$html_total_pages = sprintf( "%s", number_format_i18n( $total_pages ) );
$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
if ( $disable_next ) {
$page_links[] = '›';
} else {
$page_links[] = sprintf(
"%s%s",
esc_url( add_query_arg( 'paged', min( $total_pages, $current + 1 ), $current_url ) ),
__( 'Next page' ),
'›'
);
}
if ( $disable_last ) {
$page_links[] = '»';
} else {
$page_links[] = sprintf(
"%s%s",
esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
__( 'Last page' ),
'»'
);
}
$pagination_links_class = 'pagination-links';
if ( ! empty( $infinite_scroll ) ) {
$pagination_links_class .= ' hide-if-js';
}
$output .= "\n';
if ( $total_pages ) {
$page_class = $total_pages < 2 ? ' one-page' : '';
} else {
$page_class = ' no-pages';
}
$this->_pagination = "$output
";
echo $this->_pagination;
}
/**
* Get a list of columns. The format is:
* 'internal-name' => 'Title'
*
* @since 3.1.0
* @abstract
*
* @return array
*/
public function get_columns() {
die( 'function PUM_ListTable::get_columns() must be over-ridden in a sub-class.' );
}
/**
* Get a list of sortable columns. The format is:
* 'internal-name' => 'orderby'
* or
* 'internal-name' => array( 'orderby', true )
*
* The second format will make the initial sorting order be descending
*
* @since 3.1.0
*
* @return array
*/
protected function get_sortable_columns() {
return [];
}
/**
* Gets the name of the default primary column.
*
* @since 4.3.0
*
* @return string Name of the default primary column, in this case, an empty string.
*/
protected function get_default_primary_column_name() {
$columns = $this->get_columns();
$column = '';
if ( empty( $columns ) ) {
return $column;
}
// We need a primary defined so responsive views show something,
// so let's fall back to the first non-checkbox column.
foreach ( $columns as $col => $column_name ) {
if ( 'cb' === $col ) {
continue;
}
$column = $col;
break;
}
return $column;
}
/**
* Public wrapper for PUM_ListTable::get_default_primary_column_name().
*
* @since 4.4.0
*
* @return string Name of the default primary column.
*/
public function get_primary_column() {
return $this->get_primary_column_name();
}
/**
* Gets the name of the primary column.
*
* @since 4.3.0
*
* @return string The name of the primary column.
*/
protected function get_primary_column_name() {
$columns = get_column_headers( $this->screen );
$default = $this->get_default_primary_column_name();
// If the primary column doesn't exist fall back to the
// first non-checkbox column.
if ( ! isset( $columns[ $default ] ) ) {
$default = self::get_default_primary_column_name();
}
/**
* Filters the name of the primary column for the current list table.
*
* @since 4.3.0
*
* @param string $default Column name default for the specific list table, e.g. 'name'.
* @param string $context Screen ID for specific list table, e.g. 'plugins'.
*/
$column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
$column = $default;
}
return $column;
}
/**
* Get a list of all, hidden and sortable columns, with filter applied
*
* @since 3.1.0
*
* @return array
*/
protected function get_column_info() {
// $_column_headers is already set / cached
if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) {
// Back-compat for list tables that have been manually setting $_column_headers for horse reasons.
// In 4.3, we added a fourth argument for primary column.
$column_headers = [ [], [], [], $this->get_primary_column_name() ];
foreach ( $this->_column_headers as $key => $value ) {
$column_headers[ $key ] = $value;
}
return $column_headers;
}
$columns = get_column_headers( $this->screen );
$hidden = get_hidden_columns( $this->screen );
$sortable_columns = $this->get_sortable_columns();
/**
* Filters the list table sortable columns for a specific screen.
*
* The dynamic portion of the hook name, `$this->screen->id`, refers
* to the ID of the current screen, usually a string.
*
* @since 3.5.0
*
* @param array $sortable_columns An array of sortable columns.
*/
$_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
$sortable = [];
foreach ( $_sortable as $id => $data ) {
if ( empty( $data ) ) {
continue;
}
$data = (array) $data;
if ( ! isset( $data[1] ) ) {
$data[1] = false;
}
$sortable[ $id ] = $data;
}
$primary = $this->get_primary_column_name();
$this->_column_headers = [ $columns, $hidden, $sortable, $primary ];
return $this->_column_headers;
}
/**
* Return number of visible columns
*
* @since 3.1.0
*
* @return int
*/
public function get_column_count() {
list ( $columns, $hidden ) = $this->get_column_info();
$hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
return count( $columns ) - count( $hidden );
}
/**
* Print column headers, accounting for hidden and sortable columns.
*
* @since 3.1.0
*
* @staticvar int $cb_counter
*
* @param bool $with_id Whether to set the id attribute or not
*/
public function print_column_headers( $with_id = true ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
$current_url = remove_query_arg( 'paged', $current_url );
if ( isset( $_GET['orderby'] ) ) {
$current_orderby = $_GET['orderby'];
} else {
$current_orderby = '';
}
if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
$current_order = 'desc';
} else {
$current_order = 'asc';
}
if ( ! empty( $columns['cb'] ) ) {
static $cb_counter = 1;
$columns['cb'] = ''
. '';
$cb_counter++;
}
foreach ( $columns as $column_key => $column_display_name ) {
$class = [ 'manage-column', "column-$column_key" ];
if ( in_array( $column_key, $hidden ) ) {
$class[] = 'hidden';
}
if ( 'cb' === $column_key ) {
$class[] = 'check-column';
} elseif ( in_array( $column_key, [ 'posts', 'comments', 'links' ] ) ) {
$class[] = 'num';
}
if ( $column_key === $primary ) {
$class[] = 'column-primary';
}
if ( isset( $sortable[ $column_key ] ) ) {
list( $orderby, $desc_first ) = $sortable[ $column_key ];
if ( $current_orderby === $orderby ) {
$order = 'asc' === $current_order ? 'desc' : 'asc';
$class[] = 'sorted';
$class[] = $current_order;
} else {
$order = $desc_first ? 'desc' : 'asc';
$class[] = 'sortable';
$class[] = $desc_first ? 'asc' : 'desc';
}
$column_display_name = '' . $column_display_name . '';
}
$tag = ( 'cb' === $column_key ) ? 'td' : 'th';
$scope = ( 'th' === $tag ) ? 'scope="col"' : '';
$id = $with_id ? "id='$column_key'" : '';
if ( ! empty( $class ) ) {
$class = "class='" . join( ' ', $class ) . "'";
}
echo "<$tag $scope $id $class>$column_display_name$tag>";
}
}
/**
* Display the table
*
* @since 3.1.0
*/
public function display() {
$singular = $this->_args['singular'];
$this->display_tablenav( 'top' );
$this->screen->render_screen_reader_content( 'heading_list' );
?>
print_column_headers(); ?>
>
display_rows_or_placeholder(); ?>
print_column_headers( false ); ?>
display_tablenav( 'bottom' );
}
/**
* Get a list of CSS classes for the PUM_ListTable table tag.
*
* @since 3.1.0
*
* @return array List of CSS classes for the table tag.
*/
protected function get_table_classes() {
return [ 'widefat', 'fixed', 'striped', $this->_args['plural'] ];
}
/**
* Generate the table navigation above or below the table
*
* @since 3.1.0
* @param string $which
*/
protected function display_tablenav( $which ) {
if ( 'top' === $which ) {
wp_nonce_field( 'bulk-' . $this->_args['plural'] );
}
?>
has_items() ) : ?>
bulk_actions( $which ); ?>
extra_tablenav( $which );
$this->pagination( $which );
?>
has_items() ) {
$this->display_rows();
} else {
echo '';
$this->no_items();
echo ' |
';
}
}
/**
* Generate the table rows
*
* @since 3.1.0
*/
public function display_rows() {
foreach ( $this->items as $item ) {
$this->single_row( $item );
}
}
/**
* Generates content for a single row of the table
*
* @since 3.1.0
*
* @param object $item The current item
*/
public function single_row( $item ) {
echo '';
$this->single_row_columns( $item );
echo '
';
}
/**
*
* @param object $item
* @param string $column_name
*/
protected function column_default( $item, $column_name ) {}
/**
*
* @param object $item
*/
protected function column_cb( $item ) {}
/**
* Generates the columns for a single row of the table
*
* @since 3.1.0
*
* @param object $item The current item
*/
protected function single_row_columns( $item ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
foreach ( $columns as $column_name => $column_display_name ) {
$classes = "$column_name column-$column_name";
if ( $primary === $column_name ) {
$classes .= ' has-row-actions column-primary';
}
if ( in_array( $column_name, $hidden ) ) {
$classes .= ' hidden';
}
// Comments column uses HTML in the display name with screen reader text.
// Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
$data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
$attributes = "class='$classes' $data";
if ( 'cb' === $column_name ) {
echo '