Make WordPress Core


Ignore:
Timestamp:
10/20/2026 05:49:16 AM (30 hours ago)
Author:
westonruter
Message:

Posts, Post Types: Add pre_wp_count_attachments filter.

Introduces the pre_wp_count_attachments filter to wp_count_attachments(), the counterpart of pre_wp_count_posts. Returning a stdClass object short-circuits the function, skipping the object cache lookup and both of its queries. Since the counts cache group is non-persistent, those queries otherwise run on every request that needs the counts, and on a site with millions of attachments the GROUP BY post_mime_type aggregate alone can take several seconds. The filter allows the counts to be served instead from a value pre-computed in the background.

Unlike post statuses, the set of MIME types is not known ahead of time, so only a missing trash count is filled in with zero. The filtered value should therefore contain a count for every MIME type matching $mime_type, and only those types. As with pre_wp_count_posts, the value is not cached and is passed through the wp_count_attachments filter.

The pre_wp_count_posts filter introduced in r64245 is brought in line with the new one. A filtered value now short-circuits only when it is a stdClass object: any other non-null value was previously cast to an object, turning false into a nonsensical result, and filling in missing counts on another class can trigger a dynamic property deprecation. Both filters also clone the returned object, so that a callback which keeps it, such as in a static variable, does not have it modified by core or by later callbacks on the wp_count_posts and wp_count_attachments filters.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/14210.
Follow-up to r64245.

Props jdeep, westonruter, peterwilsoncc.
See #66098.
Fixes #66291.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r64583 r64589  
    35453545         * Filters the post counts before the query is run.
    35463546         *
    3547          * Returning a non-null value short-circuits wp_count_posts(), skipping both
    3548          * the object cache lookup and the database query. This allows the counts to
    3549          * be served from another source, such as a value pre-computed in the
    3550          * background, when an exact real-time count is not required.
    3551          *
    3552          * Any registered post status missing from the filtered value are added
     3547         * Returning a stdClass object short-circuits wp_count_posts(), skipping
     3548         * both the object cache lookup and the database query. This allows the
     3549         * counts to be served from another source, such as a value pre-computed in
     3550         * the background, when an exact real-time count is not required.
     3551         *
     3552         * Any registered post status missing from the filtered value is added
    35533553         * to the result and set to zero.
    35543554         *
    … …  
    35663566        $counts = apply_filters( 'pre_wp_count_posts', null, $type, $perm );
    35673567
    3568         if ( null !== $counts ) {
    3569                 $counts = (object) $counts;
     3568        if ( $counts instanceof stdClass ) {
     3569                $counts = clone $counts;
    35703570
    35713571                foreach ( get_post_stati() as $status ) {
    … …  
    36693669function wp_count_attachments( $mime_type = '' ) {
    36703670        global $wpdb;
     3671
     3672        /**
     3673         * Filters the attachment counts before the query is run.
     3674         *
     3675         * Returning a stdClass object short-circuits wp_count_attachments(),
     3676         * skipping both the object cache lookup and the database queries. This
     3677         * allows the counts to be served from another source, such as a value
     3678         * pre-computed in the background, when an exact real-time count is not
     3679         * required.
     3680         *
     3681         * If the filtered value does not contain a trash count, one is added to the
     3682         * result and set to zero. Missing MIME types are not added, as they depend on
     3683         * the attachments that exist. The filtered value should therefore contain a
     3684         * count for every MIME type matching `$mime_type` that has attachments,
     3685         * including types first uploaded after the value was computed, as callers
     3686         * may read the count for any MIME type that exists. It should also contain
     3687         * only MIME types matching `$mime_type`, with a trash count limited to
     3688         * attachments of those types, as the default query does.
     3689         *
     3690         * The returned value is not cached and passed through the
     3691         * {@see 'wp_count_attachments'} filter.
     3692         *
     3693         * @since 7.2.0
     3694         *
     3695         * @param stdClass|null   $counts    An object containing the attachment counts by
     3696         *                                   mime type, or null to run the default query.
     3697         *                                   Default null.
     3698         * @param string|string[] $mime_type Array or comma-separated list of MIME patterns.
     3699         */
     3700        $counts = apply_filters( 'pre_wp_count_attachments', null, $mime_type );
     3701
     3702        if ( $counts instanceof stdClass ) {
     3703                $counts = clone $counts;
     3704
     3705                if ( ! isset( $counts->trash ) ) {
     3706                        $counts->trash = 0;
     3707                }
     3708
     3709                /** This filter is documented in wp-includes/post.php */
     3710                return apply_filters( 'wp_count_attachments', $counts, $mime_type );
     3711        }
    36713712
    36723713        $cache_key = sprintf(
Note: See TracChangeset for help on using the changeset viewer.