'cwbtn_payment', 'plural' => 'cwbtn_payments', 'ajax' => false, ] ); } public function get_columns(): array { return [ 'title' => __( 'For', 'cryptoway-button' ), 'amount' => __( 'Amount', 'cryptoway-button' ), 'coins' => __( 'Invoiced / paid', 'cryptoway-button' ), 'status' => __( 'Status', 'cryptoway-button' ), 'invoice' => __( 'Invoice', 'cryptoway-button' ), 'date' => __( 'Started', 'cryptoway-button' ), ]; } protected function get_views(): array { $counts = $this->counts(); $current = $this->current_status(); $views = []; $total = array_sum( $counts ); $views['all'] = sprintf( '%3$s (%4$d)', esc_url( Admin::payments_url() ), '' === $current ? ' class="current"' : '', esc_html__( 'All', 'cryptoway-button' ), $total ); foreach ( Payment::status_labels() as $status => $label ) { if ( empty( $counts[ $status ] ) || Payment::STATUS_NEW === $status ) { continue; } $views[ $status ] = sprintf( '%3$s (%4$d)', esc_url( add_query_arg( 'status', $status, Admin::payments_url() ) ), $status === $current ? ' class="current"' : '', esc_html( $label ), (int) $counts[ $status ] ); } return $views; } /** Payments per status, in one query. */ private function counts(): array { global $wpdb; // phpcs:disable WordPress.DB.DirectDatabaseQuery -- one grouped count for the status filter links; WP_Query has no GROUP BY. $rows = $wpdb->get_results( $wpdb->prepare( "SELECT pm.meta_value AS status, COUNT(*) AS n FROM {$wpdb->postmeta} pm JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key = %s AND p.post_type = %s GROUP BY pm.meta_value", Payment::META_STATUS, Payment::POST_TYPE ), ARRAY_A ); // phpcs:enable WordPress.DB.DirectDatabaseQuery $counts = []; foreach ( (array) $rows as $row ) { $counts[ (string) $row['status'] ] = (int) $row['n']; } return $counts; } private function current_status(): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- a read-only list filter. $status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : ''; return array_key_exists( $status, Payment::status_labels() ) ? $status : ''; } private function search_term(): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- a read-only list search. return isset( $_GET['s'] ) ? trim( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) : ''; } public function prepare_items(): void { $this->_column_headers = [ $this->get_columns(), [], [] ]; $page = max( 1, $this->get_pagenum() ); $status = $this->current_status(); $search = $this->search_term(); $args = [ 'post_type' => Payment::POST_TYPE, 'post_status' => [ 'private' ], 'posts_per_page' => self::PER_PAGE, 'paged' => $page, 'orderby' => 'ID', 'order' => 'DESC', // Whole posts with their meta: two queries for the page instead of two per row. 'update_post_meta_cache' => true, 'update_post_term_cache' => false, ]; $meta = []; if ( '' !== $status ) { $meta[] = [ 'key' => Payment::META_STATUS, 'value' => $status ]; } if ( '' !== $search ) { // An invoice number or an external id is looked up exactly; anything else by title. if ( preg_match( '/^[A-Za-z0-9._-]{6,64}$/', $search ) && ( str_contains( $search, '-' ) || 1 === preg_match( '/^[0-9a-fA-F]+$/', $search ) ) ) { $meta[] = [ 'relation' => 'OR', [ 'key' => Payment::META_INVOICE_ID, 'value' => $search ], [ 'key' => Payment::META_EXTERNAL_ID, 'value' => $search ], [ 'key' => Payment::META_TX_HASH, 'value' => $search ], ]; } else { $args['s'] = $search; } } if ( $meta ) { $args['meta_query'] = count( $meta ) > 1 ? array_merge( [ 'relation' => 'AND' ], $meta ) : $meta; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- the list is filtered by status; 20 rows a page. } $query = new \WP_Query( $args ); $this->items = array_values( array_filter( array_map( static fn( $post ): ?Payment => Payment::get( (int) ( $post instanceof \WP_Post ? $post->ID : $post ) ), (array) $query->posts ) ) ); $this->set_pagination_args( [ 'total_items' => (int) $query->found_posts, 'per_page' => self::PER_PAGE, 'total_pages' => (int) $query->max_num_pages, ] ); } public function no_items(): void { esc_html_e( 'No payments yet.', 'cryptoway-button' ); } /** * @param Payment $item */ protected function column_title( $item ): string { $title = '' . esc_html( $item->title() ) . ''; $payer = $item->payer(); $meta = []; if ( ! empty( $payer['name'] ) ) { $meta[] = esc_html( $payer['name'] ); } if ( ! empty( $payer['email'] ) ) { $meta[] = esc_html( $payer['email'] ); } $actions = [ 'view' => '' . esc_html__( 'View', 'cryptoway-button' ) . '', ]; if ( '' !== $item->invoice_id() && Settings::keys_present() ) { $actions['check'] = '' . esc_html__( 'Check', 'cryptoway-button' ) . ''; } return '' . $title . '' . ( $meta ? '
' . esc_html( $id ) . '';
}
/**
* @param Payment $item
*/
protected function column_date( $item ): string {
return esc_html( Admin::format_time( $item->created_at() ) );
}
/**
* @param Payment $item
*/
protected function column_default( $item, $column_name ): string {
return '';
}
}