*/ abstract class Activities_List_Table { /** * Type of data to display (activity, location, activity_archive) * * @var string */ protected $type; /** * Current ordering of a columm * * @var string */ protected $order = 'asc'; /** * Reverse ordering of a columm * * @var string */ protected $order_switch = 'desc'; /** * Current column whitch is ordered * * @var string */ protected $orderby = 'name'; /** * Current url * * @var string */ protected $current_url; /** * Pagination object * * @var Activities_Pagination */ protected $pagination; /** * Array containing data to be printed on the page * * @var array */ protected $items; /** * Initializes data required to begin creating the page * * @param array $columns Information about the columns to display * @param string $type Type to display (activity, location, activity_archive) */ public function __construct() { } /** * Builds the page * * @return string The page to display */ public function display() { global $wpdb; $output = ''; $table_name = $this->get_table_name(); $current_url = ( isset($_SERVER['HTTPS'] ) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $current_url = remove_query_arg( 'action', $current_url ); $current_url = remove_query_arg( 'item_id', $current_url ); $current_url = remove_query_arg( ACTIVITIES_ARCHIVE_NONCE_GET, $current_url ); $output .= Activities_Admin::get_messages(); $items_per_page = Activities_Options::get_user_option( $this->type, 'items_per_page' ); $filters = $this->get_filters(); $sql_select = $this->get_additional_sql_select(); array_unshift( $sql_select, 'i.*' ); $sql_select = implode( ', ', $sql_select ); $sql_joins = $this->build_sql_joins(); $count_sql_joins = $this->build_count_sql_joins( $filters ); $sql_where = $this->build_where( $filters ); $sql_order = $this->build_sql_order(); $total_items = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name i $count_sql_joins $sql_where" ); $this->pagination = new Activities_Pagination( $total_items, $items_per_page ); $sql_limit_offset = $this->pagination->get_sql(); if ( $this->pagination->check_if_paged() ) { $current_url = remove_query_arg( 'paged', $current_url ); } $this->items = $wpdb->get_results( "SELECT $sql_select FROM $table_name i $sql_joins $sql_where $sql_order $sql_limit_offset ", ARRAY_A ); $this->current_url = $current_url; //Url ready, start output building $output .= $this->field_filters( $filters ); $output .= '
'; $output .= '
'; $output .= $this->build_bulk_actions(); $output .= $this->pagination->get_pagination_control( $current_url, $this->type ); $output .= '
'; $output .= $this->get_table(); $output .= '
'; $output .= '
'; $output .= $this->pagination->get_pagination_control( $current_url, $this->type ); $output .= '
'; return $output; } /** * Get search input for the db query * * @return array Filters */ protected function get_filters() { $filters = array(); if ( isset( $_POST['apply_filters'] ) && isset( $_POST['filters'] ) && is_array( $_POST['filters'] ) ) { $default_filters = Activities_Options::get_default_user_option( $this->type, 'filters' ); foreach ($_POST['filters'] as $key => $value) { $key = sanitize_key( $key ); if ( array_key_exists( $key, $default_filters ) ) { $filters[$key] = sanitize_text_field( $value ); } } Activities_Options::update_user_option( $this->type, 'filters', $filters ); } else if ( isset( $_POST['clear_filters'] ) ) { Activities_Options::delete_user_option( $this->type, 'filters' ); } if ( !isset( $_POST['apply_filters'] ) ) { $filters = Activities_Options::get_user_option( $this->type, 'filters' ); } return $filters; } /** * Get db table name * * @return string */ abstract protected function get_table_name(); /** * Get additional sql selects * * @return array Additional selects for query */ protected function get_additional_sql_select() { return array(); } /** * Build sql joins * * @return string */ protected function build_sql_joins() { return ''; } /** * Build sql joins for count query * * @param array $filters Current filters applied to the sql query * @return string */ protected function build_count_sql_joins( $filters ) { return ''; } /** * Build sql order * * @param array $filters Filters for the current page * @return string Where clause */ protected function build_sql_order() { if ( isset( $_GET['order'] ) ) { $this->order = sanitize_key( $_GET['order'] ); } if ( isset( $_GET['orderby'] ) ) { $this->orderby = sanitize_key( $_GET['orderby'] ); } $this->order_switch = $this->order == 'asc' ? 'desc' : 'asc'; $orderby = sanitize_sql_orderby( $this->orderby . ' ' . strtoupper( $this->order ) ); $order_prefix = ''; if ( $orderby ) { if ($this->orderby != 'responsible' && $this->orderby != 'location') { $order_prefix = 'i.'; } return $sql_order = sprintf( 'ORDER BY %s%s', $order_prefix, $orderby ); } else { $this->order = 'name'; $this->orderby = 'asc'; return $sql_order = 'ORDER BY i.name ASC'; } } /** * Build sql where clause for activities * * @param array $filters Filters for the current page * @return string Where clause */ protected function build_where( $filters ) { $builders = $this->get_where_builders(); $filters_str = array(); foreach ($filters as $key => $value) { if ( $value != '' ) { if ( array_key_exists( $key, $builders ) ) { $filters_str[] = call_user_func( $builders[$key], $value ); } else { $filters_str[] = sprintf ( "i.%s LIKE '%%%s%%'", $key, $value ); } } } $sql_where = ''; if ( count( $filters_str ) > 0 ) { $sql_where = 'WHERE ' . implode( ' AND ', $filters_str ); } return $sql_where; } /** * Get where builders * * @return array List of column $key => callback */ protected function get_where_builders() { return array(); } /** * Gets bulk actions * * @return array */ abstract protected function get_bulk_actions(); /** * Gets columns for the table * * @return array * 'column_key' => array( * 'hidden' => bool * 'sortable' => bool * 'display' => string * ) */ abstract protected function get_columns(); /** * Builds the table * * @return string Table */ protected function get_table() { $output = ''; $output .= ''; $output .= ''; $output .= ''; $output .= $this->get_column_headers( $this->current_url ); $output .= ''; $output .= ''; $output .= 'get_rows_or_placeholder(); $output .= ''; $output .= ''; $output .= ''; $output .= $this->get_column_headers( $this->current_url, false ); $output .= ''; $output .= ''; $output .= '
'; return $output; } /** * Builds header/footer for the table * * @param bool $with_id True to build top header, false for footer * @return string Header/Footer */ protected function get_column_headers( $with_id = true ) { $output = ''; foreach ( $this->get_columns() as $key => $info ) { $class = array( 'manage-column', "column-$key" ); $column_display_name = Activities_Admin_Utility::get_column_display( $key ); if ( $info['hidden'] ) { $class[] = 'hidden'; } if ( $key === 'cb' ) { $class[] = 'check-column'; $column_display_name = ''; $column_display_name .= ''; } if ( $key === 'name' ) { $class[] = 'column-primary'; } if ( $info['sortable'] ) { if ( $this->orderby === $key ) { $class[] = 'sorted'; $class[] = $this->order_switch; } else { $class[] = 'sortable'; $class[] = 'asc'; } $column_display_name = '' . $column_display_name . ''; } $tag = ( $key === 'cb' ) ? 'td' : 'th'; $scope = ( $tag === 'th' ) ? 'scope="col"' : ''; $id = $with_id ? "id='$key'" : ''; if ( !empty( $class ) ) { $class = "class='" . implode( ' ', $class ) . "'"; } $output .= "<$tag $scope $id $class>$column_display_name"; } return $output; } /** * Gets the rows or placeholder for the table * * @return string Rows or placeholder if 0 items */ protected function get_rows_or_placeholder() { $output = ''; if ( $this->pagination->total_items > 0 ) { foreach ( $this->items as $item ) { $output .= $this->single_row( $item ); } } else { $col_count = 0; foreach ($this->get_columns() as $info) { if ( !$info['hidden'] ) { $col_count++; } } $output .= ''; $output .= $this->get_placeholder(); $output .= ''; } return $output; } /** * Builds a single row to display * * @param array $item Data for a single row * @return string The row */ protected function single_row( $item ) { global $wpdb; $output = ''; foreach ( $this->get_columns() as $key => $info ) { $classes = "$key column-$key"; if ( $key === 'name' ) { $classes .= ' has-row-actions column-primary'; } if ( $info['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( Activities_Admin_Utility::get_column_display( $key ) ) . '"'; $attributes = "class='$classes' $data"; if ( $key === 'cb' ) { $output .= ''; $output .= ''; $output .= ''; } else { $output .= ""; $output .= $this->build_table_cell( $item, $key ); $output .= ""; } } $output .= ''; return $output; } /** * Builds a the special name cell on the table * * @param array $item Data for the cell * @return string The cell */ protected function build_table_name_cell( $item ) { $output = '
'; $output .= '' . stripslashes( wp_filter_nohtml_kses( $item['name'] ) ) . ' '; $output .= '
'; $output .= $this->build_row_actions( $this->get_item_id( $item ) ); $output .= '
'; //row-actions $output .= '
'; //name-wrap $output .= ''; return $output; } /** * Build row actions for the name cell * * * @param int $id Id of the item * @return string Row actions */ abstract protected function build_row_actions( $id ); /** * Builds a singe cell on the table * * @param array $item Data for the cell * @param string $key Cell key * @return string The cell */ protected function build_table_cell( $item, $key ) { if ( $key == 'name') { return $this->build_table_name_cell( $item ); } return stripslashes( wp_filter_nohtml_kses( $item[$key] ) ); } /** * Gets the placeholder when there are no items * * @return string Placeholder */ protected function get_placeholder() { return sprintf( esc_html__( 'No %s found.' ), acts_get_multi_item_translation( $this->type, 2 ) ); } /** * Gets the item id * * @param array $item Item data * @return int */ abstract protected function get_item_id( $item ); /** * Builds the filter part of the page * * @param array $filters Current filter values * @return string Filter box for display */ protected function field_filters( $filters ) { $output = '
'; $output .= '' . esc_html__( 'Filters', 'activities' ) . ''; $output .= '
'; foreach ($filters as $key => $value) { $output .= '
'; switch ($key) { case 'category': $output .= '

' . esc_html__( ucfirst( $key ), 'activities' ) . '

'; $output .= acts_build_select( Activities_Category::get_categories( 'id=>name' ), array( 'name' => 'filters[category]', 'selected' => $value, 'blank' => __( 'No Category Filter', 'activities' ), 'blank_val' => '' ) ); break; default: $output .= '

' . esc_html__( ucfirst( $key ), 'activities' ) . '

'; $output .= ''; break; } $output .= '
'; } $output .= '
'; $output .= get_submit_button( esc_html__( 'Apply', 'activities' ), 'button', 'apply_filters', false ) . ' '; $output .= get_submit_button( esc_html__( 'Clear', 'activities' ), 'button', 'clear_filters', false ); $output .= '
'; $output .= '
'; $output .= '
'; return $output; } /** * Builds bulk action selecter * * @param array $bulk_actions Possible bulk actions for the current page * @return string Bulk actions selecter */ function build_bulk_actions() { $bulk_actions = $this->get_bulk_actions(); $output = '
'; $output .= ' '; $output .= ''; $output .= '
'; return $output; } }