Opened 10 months ago
Last modified 8 months ago
#60154 new enhancement
Add filter hook to either get_post_stati or WP_List_Util::filter
Reported by: | Malaiac | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 6.5 |
Component: | Query | Keywords: | |
Focuses: | Cc: |
Description
In the WP_Query class, around line 2649 at this time
there is a condition if a post_type is selected
<?php if ( ! empty( $queried_post_types ) ) { .... $public_statuses = get_post_stati( array( 'public' => true ) ); $status_clauses = array(); foreach ( $public_statuses as $public_status ) { $status_clauses[] = "{$wpdb->posts}.post_status = '$public_status'"; } ...
This code does not allow to filter statuses depending on other query vars, since neither get_post_stati or wp_filter_object_list (used by get_post_stati) have any hookable filter.
User scenario : I need to filter shop_order posts by a custom taxonomy.
I need to be able to select shop_order without any assigned term from this taxonomy, but only if they're "live" ( processing, completed, etc. but not refunded, failed or cancelled), as I don't care if a cancelled Order has no assigned term from this taxonomy.
So if
$WP_Query->query_vars['post_type'] == 'shop_order' && $_GET['taxonomy'] == -1
( -1 being the value I put in the admin select field to select orders without relationship to the taxonomy )
I want to be able to filter $public_statuses = get_post_stati( array( 'public' => true ) ); to remove 'dead' statuses from the list
current where clause =
AND wp_posts.post_type = 'shop_order' AND ((wp_posts.post_status = 'wc-pending' OR wp_posts.post_status = 'wc-processing' OR wp_posts.post_status = 'wc-on-hold' OR wp_posts.post_status = 'wc-completed' OR wp_posts.post_status = 'wc-cancelled' OR wp_posts.post_status = 'wc-refunded' OR wp_posts.post_status = 'wc-failed' OR wp_posts.post_status = 'wc-partially-paid'))
expected where clause =
AND wp_posts.post_type = 'shop_order' AND ((wp_posts.post_status = 'wc-pending' OR wp_posts.post_status = 'wc-processing' OR wp_posts.post_status = 'wc-on-hold' OR wp_posts.post_status = 'wc-completed' OR wp_posts.post_status = 'wc-partially-paid'))
My own hook hooks on 'posts_where' and add the filter
<?php $where .= $wpdb->prepare( " AND ID IN ( SELECT object_id FROM ". $wpdb->term_relationships . " WHERE term_taxonomy_id = %d ) ", $term_taxonomy_id );
and since I'm filtering the $where string of the SQL query, I _could_ remove the 'dead' statuses by str_replace on the where clause, but that's really ugly
I propose this code
<?php function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_statuses; $field = ( 'names' === $output ) ? 'name' : false; return wp_filter_object_list( $wp_post_statuses, $args, $output, $operator ); }
to be replaced by this code :
<?php function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_statuses; $field = ( 'names' === $output ) ? 'name' : false; $statuses = wp_filter_object_list( $wp_post_statuses, $args, $operator, $field ); return apply_filters( 'get_post_stati', $statuses, $args, $operator, $field); }
as I would then be able to
<?php add_filter('get_post_stati', 'custom_get_post_stati', 10, 4); function custom_get_post_stati( $statuses, $args, $operator, $field ) { if( is_admin() && isset( $_GET['taxonomy'] && $_GET['taxonomy'] == -1 ) { // remove the 'dead' statuses } return $statuses; }