| 3127 | /** |
| 3128 | * Retrieves the number of objects of a specific type for a term. |
| 3129 | * |
| 3130 | * @since 5.0.0 |
| 3131 | * |
| 3132 | * @param int $term_id Term ID. |
| 3133 | * @param string $taxonomy Taxonomy name. |
| 3134 | * @param string $object_type Object type. |
| 3135 | * |
| 3136 | * @return WP_Error|int WP_Error on failure, term's object count for specified type otherwise. |
| 3137 | */ |
| 3138 | function wp_get_term_object_count( $term_id, $taxonomy, $object_type ) { |
| 3139 | if ( ! taxonomy_exists( $taxonomy ) ) { |
| 3140 | return new WP_Error( |
| 3141 | 'invalid_taxonomy', |
| 3142 | __( 'Invalid taxonomy.' ), |
| 3143 | array( |
| 3144 | 'taxonomy' => $taxonomy, |
| 3145 | ) |
| 3146 | ); |
| 3147 | } |
| 3148 | |
| 3149 | if ( ! is_object_in_taxonomy( $object_type, $taxonomy ) ) { |
| 3150 | return new WP_Error( |
| 3151 | 'invalid_object_type', |
| 3152 | __( 'Object type is not in taxonomy.' ), |
| 3153 | array( |
| 3154 | 'object_type' => $object_type, |
| 3155 | 'taxonomy' => $taxonomy, |
| 3156 | ) |
| 3157 | ); |
| 3158 | } |
| 3159 | |
| 3160 | $term = get_term( $term_id, $taxonomy ); |
| 3161 | |
| 3162 | if ( is_wp_error( $term ) ) { |
| 3163 | return $term; |
| 3164 | } |
| 3165 | |
| 3166 | $taxonomy_object = get_taxonomy( $taxonomy ); |
| 3167 | |
| 3168 | // are these right? |
| 3169 | if ( 0 === $term->count ) { |
| 3170 | $count = 0; |
| 3171 | } elseif ( 1 >= count( $taxonomy_object->object_type ) ) { |
| 3172 | $count = $term->count; |
| 3173 | } else { |
| 3174 | $count = wp_get_term_object_count_from_meta( $term_id, $object_type ); |
| 3175 | |
| 3176 | // No calculated count found for this object type. |
| 3177 | if ( false === $count ) { |
| 3178 | /** |
| 3179 | * Fires when no object count is found for a given object type. |
| 3180 | * |
| 3181 | * This action provides an opportunity for third parties to run count routines. |
| 3182 | * When the object type is a post type, the count routine is run automatically. |
| 3183 | * See wp_update_term_count_for_post_type(). |
| 3184 | * |
| 3185 | * @since 5.0.0 |
| 3186 | * |
| 3187 | * @param WP_Term $term Term object. |
| 3188 | * @param string $object_type Object type name. |
| 3189 | */ |
| 3190 | do_action( 'wp_no_term_object_count_found', $term, $object_type ); |
| 3191 | |
| 3192 | // Try one more fetch after a count has potentially been triggered. |
| 3193 | $count = (int) wp_get_term_object_count_from_meta( $term_id, $object_type ); |
| 3194 | } |
| 3195 | } |
| 3196 | |
| 3197 | /** |
| 3198 | * Filters the object count for a given term. |
| 3199 | * |
| 3200 | * @since 5.0.0 |
| 3201 | * |
| 3202 | * @param int $count Count of objects of the given `$object_type` belonging to the term. |
| 3203 | * @param WP_Term $term Term object. |
| 3204 | * @param string $object_type Object type. |
| 3205 | */ |
| 3206 | return apply_filters( 'wp_term_object_count', $count, $term, $object_type ); |
| 3207 | } |
| 3208 | |
| 3209 | /** |
| 3210 | * Triggers a term count refresh when `$object_type` is a post type. |
| 3211 | * |
| 3212 | * Term-object counts are generally recalculated at the time that term-relationships are |
| 3213 | * updated. See eg wp_set_object_terms(). But for terms that were last counted before the |
| 3214 | * introduction of term-object counts, this data will initially be missing. This function |
| 3215 | * forces a calculation of those counts when the object is a post type. Object types |
| 3216 | * that are not post types must have their own separate mechanism for triggering |
| 3217 | * these counts. |
| 3218 | * |
| 3219 | * @since 5.0.0 |
| 3220 | * |
| 3221 | * @param WP_Term $term Term object. |
| 3222 | * @param string $object_type Object type. |
| 3223 | */ |
| 3224 | function wp_update_term_count_for_post_type( $term, $object_type ) { |
| 3225 | // Non-post-types cannot be handled automatically. |
| 3226 | if ( ! post_type_exists( $object_type ) ) { |
| 3227 | return; |
| 3228 | } |
| 3229 | |
| 3230 | // Taxonomies with their own count callbacks cannot be handled automatically. |
| 3231 | $taxonomy = get_taxonomy( $term->taxonomy ); |
| 3232 | if ( ! empty( $taxonomy->update_count_callback ) ) { |
| 3233 | return; |
| 3234 | } |
| 3235 | |
| 3236 | wp_update_term_count_now( array( $term->term_taxonomy_id ), $term->taxonomy ); |
| 3237 | } |
| 3238 | |
| 3239 | /** |
| 3240 | * Get the cached term-object count from termmeta. |
| 3241 | * |
| 3242 | * @param int $term_id ID of the term. |
| 3243 | * @param string $object_type Object type. |
| 3244 | * @return bool|int Returns false when no metadata is found, which indicates that a count has not taken place. |
| 3245 | */ |
| 3246 | function wp_get_term_object_count_from_meta( $term_id, $object_type ) { |
| 3247 | $term_object_count = get_term_meta( $term_id, '_wp_object_count_' . $object_type, true ); |
| 3248 | if ( $term_object_count ) { |
| 3249 | return (int) $term_object_count; |
| 3250 | } |
| 3251 | |
| 3252 | $counted_object_types = (array) get_term_meta( $term_id, '_wp_counted_object_types', true ); |
| 3253 | |
| 3254 | // When the object type is marked counted and no meta key exists, the count is 0. |
| 3255 | if ( in_array( $object_type, $counted_object_types, true ) ) { |
| 3256 | return 0; |
| 3257 | } |
| 3258 | |
| 3259 | return false; |
| 3260 | } |
| 3261 | |
| 3806 | $term = get_term_by( 'term_taxonomy_id', $tt_id ); |
| 3807 | |
| 3808 | // Remove previous counts to prevent stale data if an object type is removed from a taxonomy. |
| 3809 | $counted_object_types = (array) get_term_meta( $term->term_id, '_wp_counted_object_types', true ); |
| 3810 | |
| 3811 | foreach ( $counted_object_types as $o_type ) { |
| 3812 | delete_term_meta( $term->term_id, '_wp_object_count_' . $o_type ); |
| 3813 | } |
| 3814 | |
| 3815 | delete_term_meta( $term->term_id, '_wp_counted_object_types' ); |
| 3816 | |
| 3817 | $term_count_meta = array(); |
| 3818 | |
| 3819 | if ( $object_types ) { |
| 3820 | foreach ( $object_types as $type ) { |
| 3821 | $current_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type = %s AND term_taxonomy_id = %d", $type, $tt_id ) ); |
| 3822 | |
| 3823 | $count += $current_count; |
| 3824 | |
| 3825 | $term_count_meta[ $type ] = $current_count; |
| 3826 | } |
| 3827 | } |
| 3828 | |