WordPress.org

Make WordPress Core

Opened 7 weeks ago

Last modified 7 weeks ago

#43995 new defect (bug)

wp_dropdown_categories(array( 'pad_counts' => true ) ) doesn't correctly pad counts on post_types with custom stati

Reported by: pbiron Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: trunk
Component: Taxonomy Keywords:
Focuses: Cc:

Description

Suppose I have the following situation:

  • a custom post type (e.g., member)
  • post type member has custom post stati (e.g., subscribed and unsubscribed)
  • ALL posts of post type member have one of these custom stati (i.e., NONE have post_status publish).
  • a hierarchical taxonomy (e.g., membership-status) is registered on post type member
  • taxonomy membership-status looks like the following:
    • Membership
      • Current
      • Expired

and that the term Current has been assigned to 10 posts, Expired has been assigned to 5 posts and that Membership has been assigned to 0 posts.

If I then call

$args = array(
    'taxonomy' => 'membership-status',
    'show_counts' => true,
    'pad_counts' => true,
    ...
);
wp_dropdown_categories( $args );

I expect to get a dropdown that looks like:

  • Membership (15)
    • Current (10)
    • Expired (5)

Instead, I get the following:

  • Membership (0)
    • Current (10)
    • Expired (5)

which is, obviously, not correctly padding the count for Membership.

Related: #11847, #13176

Change History (4)

#1 @pbiron
7 weeks ago

The problem is in _pad_term_counts() (/wp-includes/taxonomy.php#L3537):

$results = $wpdb->get_results( "SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode( ',', array_keys( $term_ids ) ) . ") AND post_type IN ('" . implode( "', '", $object_types ) . "') AND post_status = 'publish'" );

which hardcodes ...AND post_status = 'publish' into the query.

My initial stab at a fix is to replace /wp-includes/taxonomy.php#L3537 with

$post_stati = apply_filters( 'pad_term_counts_post_stati', array( 'publish' ), $taxonomy, $object_types );
$results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode(',', array_keys($term_ids)) . ") AND post_type IN ('" . implode("', '", $object_types) . "') AND post_status IN ('" . implode("', '", $post_stati) . "')");

which would allow me to write:

add_filter( 'pad_term_counts_post_stati', 'my_pad_term_counts_post_stati' ), 10, 3 );
function my_pad_term_counts_post_stati( $post_stati, $taxonomy, $object_types ) {
        if ( in_array( 'member', $object_types ) && in_array( 'membership-status', (array) $taxonomy ) ) {
                $post_stati = array( 'subscribed', 'unsubscribed' );
        }

        return $post_stati;
}

The above would certainly solve my immediate need, but there might be other more generalized use cases that would require some other solution.

If others agree that the problem is real and that some fix is desired, I'll produce a patch and some unit tests that cover my immediate need.

#2 follow-up: @Venutius
7 weeks ago

This change would also be helpful to a few other plugins I can think of, one being my own BP Post Status, but also LH Logged in Post Status and WP_Statuses. Working around this is non trivial from what I can see.

#3 in reply to: ↑ 2 @pbiron
7 weeks ago

Replying to Venutius:

This change would also be helpful to a few other plugins I can think of, one being my own BP Post Status, but also LH Logged in Post Status and WP_Statuses. Working around this is non trivial from what I can see.

Thanx for the backup on the need for a change.

I am unfamiliar with the plugins you mention. From what you know, will my proposed fix above satisfy the requirements of those plugins?

#4 @Venutius
7 weeks ago

Yes I believe so, this problem is that we need a mechanism to add additional post statuses into the search for post categories, this seems to allow that in a very accessible way.

Note: See TracTickets for help on using tickets.