gocodebox/lifterlms

View on GitHub
includes/abstracts/abstract.llms.admin.table.php

Summary

Maintainability
D
2 days
Test Coverage
F
55%
<?php
/**
 * Admin Table Abstract
 *
 * @package LifterLMS/Abstracts/Classes
 *
 * @since 3.2.0
 * @version 7.3.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * LLMS_Admin_Table abstract class.
 *
 * @since 3.2.0
 * @since 3.34.0 Added get_table_classes().
 * @since 3.37.7 Fix PHP 7.4 deprecation notice.
 */
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
     *
     * @return string
     */
    public function get_title() {
        /**
         * Filters the table title.
         *
         * The dynamic portion of this filter `{$this->id}` refers to the unique ID for the table.
         *
         * @since 3.15.0
         *
         * @param string $title The title of the table.
         */
        return apply_filters( "llms_table_get_{$this->id}_table_title", $this->title );
    }

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

    /**
     * Determine if a column is visible based on the current context.
     *
     * @since 3.15.0
     *
     * @param array  $data    Array of a single column's data from `set_columns()`.
     * @param string $context Context [display|export].
     * @return bool
     */
    private function is_col_visible( $data, $context = 'display' ) {

        // Display if 'export_only' does not exist or it does exist and is false.
        if ( 'display' === $context ) {
            return ( ! isset( $data['export_only'] ) || ! $data['export_only'] );

            // Display if exportable is set and is true.
        } elseif ( 'export' === $context ) {
            return ( isset( $data['exportable'] ) && $data['exportable'] );
        }

        return true;

    }

    /**
     * Return protected is_last_page var.
     *
     * @since 3.15.0
     *
     * @return bool
     */
    public function is_last_page() {
        return $this->is_last_page;
    }

    /**
     * Allow custom hooks to be registered for use within the class.
     *
     * @since 3.2.0
     *
     * @return void
     */
    protected function register_hooks() {}

    /**
     * Setter.
     *
     * @since 2.3.0
     *
     * @param string $key Variable name.
     * @param mixed  $val Variable data.
     * @return void
     */
    public function set( $key, $val ) {
        $this->$key = $val;
    }

    /**
     * Empty message displayed when no results are found.
     *
     * @since 3.2.0
     * @since 3.15.0 Fix filter name.
     *
     * @return string
     */
    protected function set_empty_message() {
        /**
         * Filters the default 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 default message displayed when the table is empty.
         */
        return apply_filters( 'llms_table_default_empty_message', __( 'No results were found.', 'lifterlms' ) );
    }

    /**
     * Stub used to set the title during table construction.
     *
     * @since 3.28.0
     *
     * @return string
     */
    protected function set_title() {
        return '';
    }

}