'', 'status' => '', 'batch' => '', ); /** * Constructor. */ public function __construct() { parent::__construct( array( 'singular' => 'novoverify-code', 'plural' => 'novoverify-codes', 'ajax' => false, ) ); } /** * Current filters, read from the request. * * @return array{search: string, status: string, batch: string} */ public function get_filters() { return $this->filters; } /** * Reads the filters from the request. Read-only screen state, so no nonce is needed. */ private function read_filters() { // phpcs:disable WordPress.Security.NonceVerification.Recommended $this->filters = array( 'search' => isset( $_REQUEST['s'] ) ? trim( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : '', 'status' => isset( $_REQUEST['status'] ) ? sanitize_key( wp_unslash( $_REQUEST['status'] ) ) : '', 'batch' => isset( $_REQUEST['batch'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['batch'] ) ) : '', ); // phpcs:enable WordPress.Security.NonceVerification.Recommended } /** * Columns. * * @return array */ public function get_columns() { return array( 'cb' => '', 'code' => __( 'Code', 'novoverify' ), 'product_name' => __( 'Product', 'novoverify' ), 'batch' => __( 'Batch', 'novoverify' ), 'status' => __( 'Status', 'novoverify' ), 'check_count' => __( 'Checks', 'novoverify' ), 'last_checked_at' => __( 'Last checked', 'novoverify' ), 'created_at' => __( 'Added', 'novoverify' ), ); } /** * Sortable columns. * * @return array */ protected function get_sortable_columns() { return array( 'code' => array( 'code', false ), 'product_name' => array( 'product_name', false ), 'batch' => array( 'batch', false ), 'status' => array( 'status', false ), 'check_count' => array( 'check_count', true ), 'last_checked_at' => array( 'last_checked_at', true ), 'created_at' => array( 'created_at', true ), ); } /** * Bulk actions. * * @return array */ protected function get_bulk_actions() { $actions = array( 'novoverify_revoke' => __( 'Revoke', 'novoverify' ), 'novoverify_activate' => __( 'Reactivate', 'novoverify' ), 'novoverify_delete' => __( 'Delete permanently', 'novoverify' ), ); /** * Filters the bulk actions of the codes list. Keys must start with "novoverify_". * * @param array $actions Action key => label. */ return apply_filters( 'novoverify_codes_bulk_actions', $actions ); } /** * Status views (All / Active / Revoked). * * @return array */ protected function get_views() { $counts = NovoVerify_DB::count_codes_by_status(); $current = $this->filters['status']; $base = admin_url( 'admin.php?page=novoverify-codes' ); $labels = array( /* translators: %s: number of codes. */ '' => _n_noop( 'All (%s)', 'All (%s)', 'novoverify' ), /* translators: %s: number of codes. */ NovoVerify_DB::STATUS_ACTIVE => _n_noop( 'Active (%s)', 'Active (%s)', 'novoverify' ), /* translators: %s: number of codes. */ NovoVerify_DB::STATUS_REVOKED => _n_noop( 'Revoked (%s)', 'Revoked (%s)', 'novoverify' ), ); $views = array(); foreach ( $labels as $status => $label ) { $count = '' === $status ? $counts['all'] : $counts[ $status ]; $url = '' === $status ? $base : add_query_arg( 'status', $status, $base ); $views[ '' === $status ? 'all' : $status ] = sprintf( '%3$s', esc_url( $url ), $current === $status ? ' class="current" aria-current="page"' : '', sprintf( translate_nooped_plural( $label, $count, 'novoverify' ), esc_html( number_format_i18n( $count ) ) ) ); } return $views; } /** * Batch filter shown above the table. * * @param string $which top or bottom. */ protected function extra_tablenav( $which ) { if ( 'top' !== $which ) { return; } $batches = NovoVerify_DB::get_batches(); if ( empty( $batches ) ) { return; } ?>
read_filters(); $per_page = $this->get_items_per_page( 'novoverify_codes_per_page', 20 ); // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Sorting is read-only screen state. $orderby = isset( $_REQUEST['orderby'] ) ? sanitize_key( wp_unslash( $_REQUEST['orderby'] ) ) : 'id'; $order = isset( $_REQUEST['order'] ) ? sanitize_key( wp_unslash( $_REQUEST['order'] ) ) : 'desc'; // phpcs:enable WordPress.Security.NonceVerification.Recommended $result = NovoVerify_DB::query_codes( array_merge( $this->filters, array( 'orderby' => $orderby, 'order' => $order, 'per_page' => $per_page, 'page' => $this->get_pagenum(), ) ) ); $this->items = $result['items']; $this->set_pagination_args( array( 'total_items' => $result['total'], 'per_page' => $per_page, 'total_pages' => (int) ceil( $result['total'] / $per_page ), ) ); $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns(), 'code' ); } /** * Message when there are no codes. */ public function no_items() { if ( '' !== $this->filters['search'] || '' !== $this->filters['status'] || '' !== $this->filters['batch'] ) { esc_html_e( 'No codes match your filters.', 'novoverify' ); return; } printf( /* translators: 1: "Add New Code" link, 2: "Import" link. */ esc_html__( 'No codes yet. %1$s or %2$s.', 'novoverify' ), '' . esc_html__( 'Add a code', 'novoverify' ) . '', '' . esc_html__( 'import codes from a CSV file', 'novoverify' ) . '' ); } /** * Checkbox column. * * @param object $item Row. * @return string */ protected function column_cb( $item ) { return sprintf( '', (int) $item->id, /* translators: %s: code. */ esc_html( sprintf( __( 'Select %s', 'novoverify' ), $item->display_code ) ) ); } /** * Code column with row actions. * * @param object $item Row. * @return string */ protected function column_code( $item ) { $id = (int) $item->id; $display = '' !== $item->display_code ? $item->display_code : $item->code; $edit_url = admin_url( 'admin.php?page=novoverify-codes&action=edit&id=' . $id ); $is_revoked = NovoVerify_DB::STATUS_REVOKED === $item->status; $toggle = $is_revoked ? 'activate' : 'revoke'; $actions = array( 'edit' => sprintf( '%s', esc_url( $edit_url ), esc_html__( 'Edit', 'novoverify' ) ), $toggle => sprintf( '%s', esc_url( NovoVerify_Codes_Page::row_action_url( $toggle, $id ) ), $is_revoked ? esc_html__( 'Reactivate', 'novoverify' ) : esc_html__( 'Revoke', 'novoverify' ) ), 'delete' => sprintf( '%s', esc_url( NovoVerify_Codes_Page::row_action_url( 'delete', $id ) ), /* translators: %s: code. */ esc_attr( sprintf( __( 'Delete the code %s permanently? Its check history is kept.', 'novoverify' ), $display ) ), esc_html__( 'Delete permanently', 'novoverify' ) ), ); /** * Filters the row actions of a code. Values are HTML and must be escaped. * * @param array $actions Row actions. * @param object $item Code row. */ $actions = apply_filters( 'novoverify_codes_row_actions', $actions, $item ); return sprintf( '%s%s', esc_url( $edit_url ), esc_html( $display ), $this->row_actions( $actions ) ); } /** * Status column. * * @param object $item Row. * @return string */ protected function column_status( $item ) { if ( NovoVerify_DB::STATUS_REVOKED === $item->status ) { return '' . esc_html__( 'Revoked', 'novoverify' ) . ''; } return '' . esc_html__( 'Active', 'novoverify' ) . ''; } /** * Check count column. * * @param object $item Row. * @return string */ protected function column_check_count( $item ) { return esc_html( number_format_i18n( (int) $item->check_count ) ); } /** * Last checked column. * * @param object $item Row. * @return string */ protected function column_last_checked_at( $item ) { $date = NovoVerify_Codes::format_datetime( $item->last_checked_at ); return '' !== $date ? esc_html( $date ) : '' . esc_html__( 'Never', 'novoverify' ) . ''; } /** * Added column. * * @param object $item Row. * @return string */ protected function column_created_at( $item ) { return esc_html( NovoVerify_Codes::format_datetime( $item->created_at, get_option( 'date_format' ) ) ); } /** * Other text columns. * * @param object $item Row. * @param string $column_name Column. * @return string */ protected function column_default( $item, $column_name ) { $value = isset( $item->$column_name ) ? (string) $item->$column_name : ''; return '' !== $value ? esc_html( $value ) : ''; } }