self::param( self::PARAM_SEARCH ), 'status' => sanitize_title( self::param( self::PARAM_STATUS ) ), 'category' => sanitize_title( self::param( self::PARAM_CATEGORY ) ), 'sort' => self::SORT_NEW === $sort ? self::SORT_NEW : self::SORT_TOP, 'page' => max( 1, absint( self::param( self::PARAM_PAGE ) ) ), ]; } /** * Builds the query for one page of a board. * * @param int $board_id Board term ID, or 0 for the requests of every board. * @param array{search: string, status: string, category: string, sort: string, page: int} $filters Filters, as from filters_from_request(). * @param int $per_page Requests per page. * @return array WP_Query arguments. */ public static function args( int $board_id, array $filters, int $per_page ): array { $tax_query = []; if ( $board_id ) { $tax_query[] = [ 'taxonomy' => BoardTaxonomy::NAME, 'field' => 'term_id', 'terms' => $board_id, ]; } $closed = StatusTaxonomy::closed_ids(); if ( '' === $filters['status'] && $closed ) { // By default the board shows what people can still vote on. $tax_query[] = [ 'taxonomy' => StatusTaxonomy::NAME, 'field' => 'term_id', 'terms' => $closed, 'operator' => 'NOT IN', ]; } elseif ( '' !== $filters['status'] && self::STATUS_ALL !== $filters['status'] ) { $tax_query[] = [ 'taxonomy' => StatusTaxonomy::NAME, 'field' => 'slug', 'terms' => $filters['status'], ]; } if ( '' !== $filters['category'] ) { $tax_query[] = [ 'taxonomy' => CategoryTaxonomy::NAME, 'field' => 'slug', 'terms' => $filters['category'], ]; } $args = [ 'post_type' => RequestPostType::NAME, 'post_status' => 'publish', 'has_password' => false, 'posts_per_page' => $per_page, 'paged' => $filters['page'], 'ignore_sticky_posts' => true, 'tax_query' => $tax_query, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Boards, statuses and categories are taxonomies. ]; if ( '' !== $filters['search'] ) { $args['s'] = $filters['search']; } if ( self::SORT_TOP === $filters['sort'] ) { // Every request has this meta from creation, so none drop out of the list. $args['meta_key'] = RequestPostType::META_VOTES; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Sorting by the stored vote count. $args['orderby'] = [ 'meta_value_num' => 'DESC', 'date' => 'DESC', ]; } else { $args['orderby'] = [ 'date' => 'DESC', 'ID' => 'DESC', ]; } return $args; } /** * Returns a GET parameter as sanitized text, or ''. * * @param string $name Parameter name. */ private static function param( string $name ): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filters from a GET form. return isset( $_GET[ $name ] ) && is_string( $_GET[ $name ] ) ? sanitize_text_field( wp_unslash( $_GET[ $name ] ) ) : ''; } }