Make WordPress Core

Opened 5 months ago

Last modified 3 months ago

#60154 new enhancement

Add filter hook to either get_post_stati or WP_List_Util::filter

Reported by: malaiac's profile 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;
}

Change History (0)

Note: See TracTickets for help on using tickets.