LLMS_Admin_Table

LLMS_Admin_Table abstract class.


Source Source

File: includes/abstracts/abstract.llms.admin.table.php

abstract class LLMS_Admin_Table extends LLMS_Abstract_Exportable_Admin_Table {

	/**
	 * Unique ID for the Table.
	 *
	 * @var string
	 */
	protected $id = '';

	/**
	 * When pagination is enabled, the current page.
	 *
	 * @var integer
	 */
	protected $current_page = 1;

	/**
	 * Value of the field being filtered by.
	 *
	 * @var string Only applicable if $filterby is set.
	 */
	protected $filter = '';

	/**
	 * Field results are filtered by.
	 *
	 * @var string
	 */
	protected $filterby = '';

	/**
	 * Is the Table Exportable?
	 *
	 * @var bool
	 */
	protected $is_exportable = false;

	/**
	 * When pagination enabled, determines if this is the last page of results.
	 *
	 * @var bool
	 */
	protected $is_last_page = true;

	/**
	 * If true, tfoot will add ajax pagination links.
	 *
	 * @var bool
	 */
	protected $is_paginated = false;

	/**
	 * Determine if the table is filterable.
	 *
	 * @var bool
	 */
	protected $is_filterable = false;

	/**
	 * If true will be a table with a larger font size.
	 *
	 * @var bool
	 */
	protected $is_large = false;

	/**
	 * Determine of the table is searchable.
	 *
	 * @var bool
	 */
	protected $is_searchable = false;

	/**
	 * If true, tbody will be zebra striped.
	 *
	 * @var bool
	 */
	protected $is_zebra = true;

	/**
	 * If an integer supplied, used to jump to last page.
	 *
	 * @var int
	 */
	protected $max_pages = null;

	/**
	 * Results sort order.
	 *
	 * @var string 'ASC' or 'DESC'.
	 *             Only applicable of $orderby is not set.
	 */
	protected $order = '';

	/**
	 * Field results are sorted by.
	 *
	 * @var string
	 */
	protected $orderby = '';

	/**
	 * Number of records to display per page.
	 *
	 * @var int
	 */
	protected $per_page = -1;

	/**
	 * The search query submitted for a searchable table.
	 *
	 * @var string
	 */
	protected $search = '';

	/**
	 * Table Data.
	 *
	 * @var array Array of objects or arrays.
	 *            Each item represents as row in the table's body, each item is a cell.
	 */
	protected $tbody_data = array();

	/**
	 * Table Title Displayed on Screen.
	 *
	 * @var string
	 */
	protected $title = '';

	/**
	 * Retrieve data for a cell.
	 *
	 * @since 3.2.0
	 *
	 * @param string $key  The column ID/key.
	 * @param mixed  $data Object/array of data that the function can use to extract the data.
	 * @return mixed
	 */
	abstract protected function get_data( $key, $data );

	/**
	 * Execute a query to retrieve results from the table.
	 *
	 * @since 3.2.0
	 *
	 * @param array $args Array of query args.
	 * @return mixed
	 */
	abstract public function get_results( $args = array() );

	/**
	 * Define the structure of arguments used to pass to the get_results method.
	 *
	 * @since 2.3.0
	 *
	 * @return array
	 */
	abstract public function set_args();

	/**
	 * Define the structure of the table.
	 *
	 * @since 3.2.0
	 *
	 * @return array
	 */
	abstract protected function set_columns();

	/**
	 * Constructor.
	 *
	 * @since 3.2.0
	 *
	 * @return void
	 */
	public function __construct() {
		$this->title = $this->set_title();
		$this->register_hooks();
	}

	/**
	 * Ensure that a valid array of data is passed to a query.
	 *
	 * Used by AJAX methods to clean unnecessary parameters before passing the request data
	 * to the get_results function.
	 *
	 * @since 3.2.0
	 *
	 * @param array $args Array of arguments
	 * @return array
	 */
	protected function clean_args( $args = array() ) {

		$allowed = array_keys( $this->get_args() );

		foreach ( $args as $key => $val ) {
			if ( ! in_array( $key, $allowed ) ) {
				unset( $args[ $key ] );
			}
		}

		return $args;

	}

	/**
	 * Ensures that all data requested by $this->get_data is filterable
	 * before being output on screen / in the export file.
	 *
	 * @since 3.2.0
	 * @since 3.17.6 Unknown.
	 *
	 * @param mixed  $value   Value to be displayed.
	 * @param string $key     Column key/ID.
	 * @param mixed  $data    Original data object/array.
	 * @param string $context Display context [display|export].
	 * @return mixed
	 */
	protected function filter_get_data( $value, $key, $data, $context = 'display' ) {
		/**
		 * Filters the table data.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.2.0
		 *
		 * @param mixed            $value        Value to be displayed.
		 * @param string           $key          Column key/ID.
		 * @param mixed            $data         Original data object/array.
		 * @param string           $context      Display context [display|export].
		 * @param LLMS_Admin_Table $table_object Instance of the class extending `LLMS_Admin_Table`.
		 */
		return apply_filters( "llms_table_get_data_{$this->id}", $value, $key, $data, $context, $this );
	}

	/**
	 * Retrieve the arguments defined in `set_args`.
	 *
	 * @since 3.2.0
	 * @since 3.15.0 Fix filter name.
	 *
	 * @return array
	 */
	public function get_args() {

		$default = array(
			'page'    => $this->get_current_page(),
			'order'   => $this->get_order(),
			'orderby' => $this->get_orderby(),
		);

		if ( $this->is_filterable ) {
			$default['filter']   = $this->get_filter();
			$default['filterby'] = $this->get_filterby();
		}

		if ( $this->is_searchable ) {
			$default['search'] = $this->get_search();
		}

		$args = wp_parse_args( $this->set_args(), $default );

		/**
		 * Filters the arguments used to build the query.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.15.0
		 *
		 * @param array $args Arguments to build the query whose results will populate the table.
		 */
		return apply_filters( "llms_table_get_args_{$this->id}", $args );
	}

	/**
	 * Retrieve the array of columns defined by set_columns.

	 * @since 3.2.0
	 * @since 3.24.0 Unknown.
	 *
	 * @param string $context Display context [display|export].
	 * @return array
	 */
	public function get_columns( $context = 'display' ) {

		/**
		 * Filters the array of table columns.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.2.0
		 *
		 * @param array  $columns The array of table columns.
		 * @param string $context Display context [display|export].
		 */
		$cols = apply_filters( "llms_table_get_{$this->id}_columns", $this->set_columns(), $context );

		if ( $this->is_exportable ) {

			foreach ( $cols as $id => $data ) {

				if ( ! $this->is_col_visible( $data, $context ) ) {
					unset( $cols[ $id ] );
				}
			}
		}

		return $cols;

	}

	/**
	 * Get the current page.
	 *
	 * @since 3.2.0
	 *
	 * @return int
	 */
	public function get_current_page() {
		return $this->current_page;
	}

	/**
	 * Get `$this->empty_msg` string.
	 *
	 * @since 3.2.0
	 * @since 3.15.0 Fix filter name.
	 *
	 * @return string
	 */
	public function get_empty_message() {
		/**
		 * Filters the message displayed when the table is empty.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.15.0
		 *
		 * @param string $columns The message displayed when the table is empty.
		 */
		return apply_filters( "llms_table_get_{$this->id}_empty_message", $this->set_empty_message() );
	}

	/**
	 * Get the text for the default/placeholder for a filterable column.
	 *
	 * @since 3.4.0
	 * @since 3.15.0 Fix filter name.
	 * @since 7.3.0 Fixed typo in function name (`is_strinp` => `is_string` ).
	 *
	 * @param string $column_id The ID of the column.
	 * @return string
	 */
	public function get_filter_placeholder( $column_id, $column_data ) {
		$placeholder = __( 'Any', 'lifterlms' );
		if ( is_array( $column_data ) && isset( $column_data['title'] ) ) {
			$placeholder = sprintf( __( 'Any %s', 'lifterlms' ), $column_data['title'] );
		} elseif ( is_string( $column_data ) ) {
			$placeholder = sprintf( __( 'Any %s', 'lifterlms' ), $column_data );
		}
		/**
		 * Filters the placeholder string for a filterable column.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.15.0
		 *
		 * @param string $placeholder Placeholder string.
		 * @param string $column_id   The ID of the column.
		 */
		return apply_filters( "llms_table_get_{$this->id}_filter_placeholder", $placeholder, $column_id );
	}

	/**
	 * Get the current filter.
	 *
	 * @since 3.4.0
	 *
	 * @return string
	 */
	public function get_filter() {
		return $this->filter;
	}

	/**
	 * Get the current field results are filtered by.
	 *
	 * @since 3.4.0
	 *
	 * @return string
	 */
	public function get_filterby() {
		return $this->filterby;
	}

	/**
	 * Retrieve a modified classname that can be passed via AJAX for new queries.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_handler() {
		return str_replace( 'LLMS_Table_', '', get_class( $this ) );
	}

	/**
	 * Retrieve the max number of pages for the table.
	 *
	 * @since 3.15.0
	 *
	 * @return int
	 */
	public function get_max_pages() {
		return $this->max_pages;
	}

	/**
	 * Get the current sort order.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_order() {
		return $this->order;
	}

	/**
	 * Get the current field results are ordered by.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_orderby() {
		return $this->orderby;
	}

	/**
	 * Get the current number of results to display per page.
	 *
	 * @since 3.28.0
	 *
	 * @return int
	 */
	public function get_per_page() {
		return $this->per_page;
	}

	/**
	 * Gets the opposite of the current order.
	 *
	 * Used to determine what order should be displayed when resorting.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	protected function get_new_order( $orderby = '' ) {

		// Current order matches submitted order, return opposite.
		if ( $this->orderby === $orderby ) {
			return ( 'ASC' === $this->order ) ? 'DESC' : 'ASC';
		} else {
			return 'ASC';
		}

	}

	/**
	 * Retrieves the current search query.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_search() {
		return esc_attr( trim( $this->search ) );
	}

	/**
	 * Returns an array of CSS class names to use on this table.
	 *
	 * @since 3.34.0
	 *
	 * @return array
	 */
	protected function get_table_classes() {
		$classes = array(
			'llms-table',
			'llms-gb-table',
			'llms-gb-table-' . $this->id,
		);

		if ( $this->is_zebra ) {
			$classes[] = 'zebra';
		}

		if ( $this->is_large ) {
			$classes[] = 'size-large';
		}

		/**
		 * Filters the CSS classes to use on the table.
		 *
		 * @since 3.34.0
		 *
		 * @param array $classes  CSS class names.
		 * @param array $table_id Id property of this table object.
		 */
		return apply_filters( 'llms_table_get_table_classes', $classes, $this->id );
	}

	/**
	 * Get HTML for the filters displayed in the head of the table.
	 *
	 * @since 3.4.0
	 *
	 * @return string
	 */
	public function get_table_filters_html() {
		ob_start();
		?>
		<div class="llms-table-filters">
			<?php foreach ( $this->get_columns() as $id => $data ) : ?>
				<?php if ( is_array( $data ) && isset( $data['filterable'] ) && is_array( $data['filterable'] ) ) : ?>
					<div class="llms-table-filter-wrap">
						<select class="llms-select2 llms-table-filter" id="<?php printf( '%1$s-%2$s-filter', $this->id, $id ); ?>" name="<?php echo $id; ?>">
							<option value="<?php echo $this->get_filter(); ?>"><?php echo $this->get_filter_placeholder( $id, $data ); ?></option>
							<?php foreach ( $data['filterable'] as $val => $name ) : ?>
								<option value="<?php echo $val; ?>"><?php echo $name; ?></option>
							<?php endforeach; ?>
						</select>
					</div>
				<?php endif; ?>
			<?php endforeach; ?>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get the HTML for the entire table.
	 *
	 * @since 3.2.0
	 * @since 3.17.8 Unknown.
	 * @since 3.37.7 Use correct argument order for implode to fix php 7.4 deprecation.
	 *
	 * @return string
	 */
	public function get_table_html() {

		$classes = $this->get_table_classes();

		ob_start();
		?>
		<div class="llms-table-wrap">
			<header class="llms-table-header">
				<?php echo $this->get_table_title_html(); ?>
				<?php if ( $this->is_searchable ) : ?>
					<?php echo $this->get_table_search_form_html(); ?>
				<?php endif; ?>
				<?php if ( $this->is_filterable ) : ?>
					<?php echo $this->get_table_filters_html(); ?>
				<?php endif; ?>
			</header>
			<table
				class="<?php echo implode( ' ', $classes ); ?>"
				data-args='<?php echo wp_json_encode( $this->get_args() ); ?>'
				data-handler="<?php echo $this->get_handler(); ?>"
				id="llms-gb-table-<?php echo $this->id; ?>"
			>
				<?php echo $this->get_thead_html(); ?>
				<?php echo $this->get_tbody_html(); ?>
				<?php echo $this->get_tfoot_html(); ?>
			</table>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get the HTML of the search form for a searchable table.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_table_search_form_html() {
		ob_start();
		?>
		<div class="llms-table-search">
			<input class="regular-text" id="<?php echo $this->id; ?>-search-input" placeholder="<?php echo $this->get_table_search_form_placeholder(); ?>" type="text">
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get the Text to be used as the placeholder in a searchable tables search input.
	 *
	 * @since 3.2.0
	 * @since 3.15.0 Fix filter name.
	 *
	 * @return string
	 */
	public function get_table_search_form_placeholder() {
		/**
		 * Filters the text to be used as the placeholder in a searchable tables search input.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.15.0
		 *
		 * @param string $text Text to be used as the placeholder in a searchable tables search input.
		 */
		return apply_filters( "llms_table_get_{$this->id}_search_placeholder", __( 'Search', 'lifterlms' ) );
	}

	/**
	 * Get the HTML for the table's title.
	 *
	 * @since 3.2.0
	 * @since 3.15.0 Unknown.
	 *
	 * @return string
	 */
	public function get_table_title_html() {
		$title = $this->get_title();
		if ( $title ) {
			return '<h2 class="llms-table-title">' . $title . '</h2>';
		} else {
			return '';
		}
	}

	/**
	 * Get `$this->tbody_data` array.

	 * @since 3.2.0
	 * @since 3.15.0 Fix filter name.
	 *
	 * @return array
	 */
	public function get_tbody_data() {
		/**
		 * Filters the array of tbody data.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.15.0
		 *
		 * @param array $tbody_data Array of data that will be used to create the table body.
		 */
		return apply_filters( "llms_table_get_{$this->id}_tbody_data", $this->tbody_data );
	}

	/**
	 * Get a tbody element for the table.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_tbody_html() {
		$data = $this->get_tbody_data();
		ob_start();
		?>
		<tbody>
			<?php if ( $data ) : ?>
				<?php foreach ( $data as $row ) : ?>
					<?php echo $this->get_tr_html( $row ); ?>
				<?php endforeach; ?>
			<?php else : ?>
				<tr><td class="llms-gb-table-empty" colspan="<?php echo $this->get_columns_count(); ?>"><p><?php echo $this->get_empty_message(); ?></p></td></tr>
			<?php endif; ?>
		</tbody>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get a tfoot element for the table.
	 *
	 * @since 3.2.0
	 * @since 3.28.0 Unknown.
	 *
	 * @return string
	 */
	public function get_tfoot_html() {
		ob_start();
		?>
		<tfoot>
			<tr>
				<th colspan="<?php echo $this->get_columns_count(); ?>">
					<?php if ( $this->is_exportable ) : ?>
						<div class="llms-table-export">
							<button class="llms-button-primary small" name="llms-table-export">
								<span class="dashicons dashicons-download"></span> <?php _e( 'Export', 'lifterlms' ); ?>
							</button>
							<?php echo $this->get_progress_bar_html( 0 ); ?>
							<em><small class="llms-table-export-msg"></small></em>
						</div>
					<?php endif; ?>

					<?php if ( $this->is_paginated ) : ?>
						<div class="llms-table-pagination">
						<?php if ( $this->max_pages ) : ?>
							<span class="llms-table-page-count"><?php printf( _x( '%1$d of %2$d', 'pagination', 'lifterlms' ), $this->current_page, $this->max_pages ); ?></span>
						<?php endif; ?>
						<?php if ( 1 !== $this->get_current_page() ) : ?>
							<?php if ( $this->max_pages ) : ?>
								<button class="llms-button-primary small" data-page="1" name="llms-table-paging"><span class="dashicons dashicons-arrow-left-alt"></span> <?php _e( 'First', 'lifterlms' ); ?></button>
							<?php endif; ?>
							<button class="llms-button-primary small" data-page="<?php echo $this->current_page - 1; ?>" name="llms-table-paging"><span class="dashicons dashicons-arrow-left-alt2"></span> <?php _e( 'Back', 'lifterlms' ); ?></button>
						<?php endif; ?>
						<?php if ( ! $this->is_last_page ) : ?>
							<button class="llms-button-primary small" data-page="<?php echo $this->current_page + 1; ?>" name="llms-table-paging"><?php _e( 'Next', 'lifterlms' ); ?> <span class="dashicons dashicons-arrow-right-alt2"></span></button>
							<?php if ( $this->max_pages ) : ?>
								<button class="llms-button-primary small" data-page="<?php echo $this->max_pages; ?>" name="llms-table-paging"><?php _e( 'Last', 'lifterlms' ); ?> <span class="dashicons dashicons-arrow-right-alt"></span></button>
							<?php endif; ?>
						<?php endif; ?>
						</div>
					<?php endif; ?>
				</th>
			</tr>
		</tfoot>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get a thead element for the table.
	 *
	 * @since 3.2.0
	 *
	 * @return string
	 */
	public function get_thead_html() {
		ob_start();
		?>
		<thead>
			<tr>
			<?php foreach ( $this->get_columns() as $id => $data ) : ?>
				<th class="<?php echo $id; ?>">
					<?php if ( is_array( $data ) ) : ?>
						<?php if ( isset( $data['sortable'] ) && $data['sortable'] ) : ?>
							<a class="llms-sortable<?php echo ( $this->get_orderby() === $id ) ? ' active' : ''; ?>" data-order="<?php echo $this->get_new_order( $id ); ?>" data-orderby="<?php echo $id; ?>" href="#llms-gb-table-resort">
								<?php echo $data['title']; ?>
								<span class="dashicons dashicons-arrow-up asc"></span>
								<span class="dashicons dashicons-arrow-down desc"></span>
							</a>
						<?php else : ?>
							<?php echo $data['title']; ?>
						<?php endif; ?>
					<?php else : ?>
						<?php echo $data; ?>
					<?php endif; ?>
				</th>
			<?php endforeach; ?>
			</tr>
		</thead>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get a CSS class list (as a string) for each TR.
	 *
	 * @since 3.24.0
	 *
	 * @param mixed $row Object/array of data that the function can use to extract the data.
	 * @return string
	 */
	protected function get_tr_classes( $row ) {
		/**
		 * Filters the CSS class of a table row.
		 *
		 * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
		 *
		 * @since 3.24.0
		 *
		 * @param string $class CSS class list (as a string) for a given TR.
		 * @param mixed  $row   Object/array of data that the function can use to extract the data.
		 */
		return apply_filters( "llms_table_get_{$this->id}_tr_classes", 'llms-table-tr', $row );
	}

	/**
	 * Get the HTML for a single row in the body of the table.
	 *
	 * @since 3.2.0
	 * @since 3.21.0 Fix action hooks names.
	 *
	 * @param mixed $row Array/object of data describing a single row in the table.
	 * @return string
	 */
	public function get_tr_html( $row ) {
		ob_start();
		/**
		 * Fired before a table `<tr>`.
		 *
		 * @since 3.21.0
		 *
		 * @param string           $row          Array/object of data describing a single row in the table.
		 * @param LLMS_Admin_Table $table_object Instance of the class extending `LLMS_Admin_Table`.
		 */
		do_action( 'llms_table_before_tr', $row, $this );
		?>
		<tr class="<?php echo esc_attr( $this->get_tr_classes( $row ) ); ?>">
		<?php foreach ( $this->get_columns() as $id => $title ) : ?>
			<td class="<?php echo $id; ?>"><?php echo $this->get_data( $id, $row ); ?></td>
		<?php endforeach; ?>
		</tr>
		<?php
		/**
		 * Fired after a table `<tr>`.
		 *
		 * @since 3.21.0
		 *
		 * @param string           $row          Array/object of data describing a single row in the table.
		 * @param LLMS_Admin_Table $table_object Instance of the class extending `LLMS_Admin_Table`.
		 */
		do_action( 'llms_table_after_tr', $row, $this );
		return ob_get_clean();
	}

	/**
	 * Get the total number of columns in the table.
	 *
	 * Useful for creating full width tds via colspan.
	 *
	 * @since 3.2.0
	 *
	 * @return int
	 */
	public function get_columns_count() {
		return count( $this->get_columns() );
	}

	/**
	 * Get the HTML to output a progress bar within a td.
	 *
	 * Improve ugly tables with a small visual flourish.
	 * Useful when displaying a percentage within a table!
	 * Bonus if the table sorts by that percentage column.
	 *
	 * @since 3.4.1
	 *
	 * @param float  $percentage The percentage to be displayed.
	 * @param string $text       Text to display over the progress bar, defaults to $percentage.
	 * @return string
	 */
	public function get_progress_bar_html( $percentage, $text = '' ) {
		$text = $text ? $text : $percentage . '%';
		return '<div class="llms-table-progress">
			<div class="llms-table-progress-bar"><div class="llms-table-progress-inner" style="width:' . $percentage . '%"></div></div>
			<span class="llms-table-progress-text">' . $text . '</span>
		</div>';
	}

	/**
	 * Get the HTML for a WP Post Link.
	 *
	 * @since 3.2.0
	 *
	 * @param int    $post_id WP Post ID.
	 * @param string $text    Optional text to display within the anchor, if none supplied $post_id if used.
	 * @return string
	 */
	public function get_post_link( $post_id, $text = '' ) {
		if ( ! $text ) {
			$text = $post_id;
		}
		return '<a href="' . esc_url( get_edit_post_link( $post_id ) ) . '">' . $text . '</a>';
	}

	/**
	 * Get the title of the table.
	 *
	 * @since 3.15.0


Top ↑

Methods Methods


Top ↑

Changelog Changelog

Changelog
Version Description
3.37.7 Fix PHP 7.4 deprecation notice.
3.34.0 Added get_table_classes().
3.2.0 Introduced.

Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.