WordPress.org

Make WordPress Core

Ticket #38280: 38280.6.diff

File 38280.6.diff, 12.1 KB (added by boonebgorges, 3 years ago)
  • src/wp-includes/taxonomy.php

    diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php
    index 1a0d170848..f89fb7d8d7 100644
    function wp_update_term_count_now( $terms, $taxonomy ) { 
    29162916        return true;
    29172917}
    29182918
     2919/**
     2920 * Retrieves the term count for a specific object type.
     2921 *
     2922 * @since 4.9.0
     2923 *
     2924 * @param int    $term_id     Term ID.
     2925 * @param string $taxonomy    Taxonomy name.
     2926 * @param string $object_type Object type.
     2927 *
     2928 * @return WP_Error|bool|int WP_Error if invalid taxonomy is passed.
     2929 *                           False if object is not in taxonomy.
     2930 *                           Object term count otherwise.
     2931 */
     2932function wp_get_term_count_for_object_type( $term_id, $taxonomy, $object_type ) {
     2933        if ( ! taxonomy_exists( $taxonomy ) ) {
     2934                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
     2935        }
     2936
     2937        if ( ! is_object_in_taxonomy( $object_type, $taxonomy ) ) {
     2938                return false;
     2939        }
     2940
     2941        $term = get_term( $term_id, $taxonomy );
     2942
     2943        if ( 0 === $term->count ) {
     2944                return 0;
     2945        }
     2946
     2947        $taxonomy_object = get_taxonomy( $taxonomy );
     2948
     2949        if ( 1 >= count( $taxonomy_object->object_type ) ) {
     2950                return $term->count;
     2951        }
     2952
     2953        $term_object_count = get_term_meta( $term_id, '_wp_object_count_' . $object_type, true );
     2954        if ( $term_object_count ) {
     2955                return (int) $term_object_count;
     2956        }
     2957
     2958        $counted_object_types = (array) get_term_meta( $term_id, '_wp_counted_object_types', true );
     2959
     2960        /*
     2961         * If the object type has been counted, and other counts exist in meta, we can
     2962         * assume this term has 0 relationships for this object type.
     2963         */
     2964        if ( in_array( $object_type, $counted_object_types, true ) ) {
     2965                foreach ( $taxonomy_object->object_type as $type ) {
     2966                        if ( $test_meta = get_term_meta( $term_id, '_wp_object_count_' . $type, true ) ) {
     2967                                return 0;
     2968                        }
     2969                }
     2970        }
     2971
     2972        // No other meta caches existed. Count and try again.
     2973        if ( wp_update_term_count_now( array( $term_id ), $taxonomy ) ) {
     2974                return wp_get_term_count_for_object_type( $term_id, $taxonomy, $object_type );
     2975        }
     2976}
     2977
    29192978//
    29202979// Cache
    29212980//
    function _update_post_term_count( $terms, $taxonomy ) { 
    34123471
    34133472        $object_types = (array) $taxonomy->object_type;
    34143473
    3415         foreach ( $object_types as &$object_type )
     3474        foreach ( $object_types as &$object_type ) {
    34163475                list( $object_type ) = explode( ':', $object_type );
     3476        }
    34173477
    34183478        $object_types = array_unique( $object_types );
    34193479
    function _update_post_term_count( $terms, $taxonomy ) { 
    34223482                $check_attachments = true;
    34233483        }
    34243484
    3425         if ( $object_types )
     3485        if ( $object_types ) {
    34263486                $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) );
     3487        }
    34273488
    34283489        foreach ( (array) $terms as $term ) {
    34293490                $count = 0;
    34303491
     3492                // Remove previous counts to prevent stale data if an object type is removed from a taxonomy.
     3493                $counted_object_types = (array) get_term_meta( $term, '_wp_counted_object_types', true );
     3494
     3495                foreach ( $counted_object_types as $o_type ) {
     3496                        delete_term_meta( $term, '_wp_object_count_' . $o_type );
     3497                }
     3498
     3499                delete_term_meta( $term, '_wp_counted_object_types' );
     3500
     3501                $term_count_meta = array();
     3502
     3503                if ( $object_types ) {
     3504                        foreach ( $object_types as $type ) {
     3505                                $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, $term ) );
     3506
     3507                                $count += $current_count;
     3508                                $term_count_meta[ $type ] = $current_count;
     3509                        }
     3510                }
     3511
    34313512                // Attachments can be 'inherit' status, we need to base count off the parent's status if so.
    3432                 if ( $check_attachments )
    3433                         $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status = 'publish' OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) = 'publish' ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) );
     3513                if ( $check_attachments ) {
     3514                        $attachment_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status = 'publish' OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) = 'publish' ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) );
     3515
     3516                        $count += $attachment_count;
     3517                        $term_count_meta['attachment'] = $attachment_count;
    34343518
    3435                 if ( $object_types )
    3436                         $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 IN ('" . implode("', '", $object_types ) . "') AND term_taxonomy_id = %d", $term ) );
     3519                        // Re-add attachment so the meta gets saved below.
     3520                        $object_types[] = 'attachment';
     3521                }
     3522
     3523                // Save individual counts for each object type in term meta.
     3524                if ( 1 < count( $term_count_meta ) ) {
     3525                        foreach ( $object_types as $type ) {
     3526                                if ( ! empty( $term_count_meta[ $type ] ) ) {
     3527                                        update_term_meta( $term, '_wp_object_count_' . $type, (int) $term_count_meta[ $type ] );
     3528                                }
     3529                        }
     3530
     3531                        update_term_meta( $term, '_wp_counted_object_types', $object_types );
     3532                } else {
     3533                        foreach ( $object_types as $type ) {
     3534                                delete_term_meta( $term, '_wp_object_count_' . $type );
     3535                        }
     3536
     3537                        delete_term_meta( $term, '_wp_counted_object_types' );
     3538                }
    34373539
    34383540                /** This action is documented in wp-includes/taxonomy.php */
    34393541                do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
    function wp_get_split_term( $old_term_id, $taxonomy ) { 
    38613963 *
    38623964 * @param int $term_id Term ID.
    38633965 * @return bool Returns false if a term is not shared between multiple taxonomies or
    3864  *              if splittng shared taxonomy terms is finished. 
     3966 *              if splittng shared taxonomy terms is finished.
    38653967 */
    38663968function wp_term_is_shared( $term_id ) {
    38673969        global $wpdb;
  • tests/phpunit/tests/term/getTerms.php

    diff --git tests/phpunit/tests/term/getTerms.php tests/phpunit/tests/term/getTerms.php
    index 575e5ca1c0..881c67a467 100644
    class Tests_Term_getTerms extends WP_UnitTestCase { 
    228228                ), $terms_id_slug );
    229229        }
    230230
    231         /**
     231        /**
    232232         * @ticket 11823
    233          */
     233         */
    234234        function test_get_terms_include_exclude() {
    235235                global $wpdb;
    236236
    class Tests_Term_getTerms extends WP_UnitTestCase { 
    22192219                $this->assertNotEquals( 'foo', $found );
    22202220        }
    22212221
     2222        /**
     2223         * @ticket 38280
     2224         */
     2225        public function test_wp_get_term_count_for_object_type_single_object_type() {
     2226                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2227                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2228
     2229                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2230
     2231                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2232        $this->assertFalse( (bool) get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2233
     2234                $term_object = get_term( $term_id, 'category' );
     2235                $this->assertEquals( 1, $term_object->count );
     2236
     2237                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2238
     2239                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2240        }
     2241
     2242        /**
     2243         * @ticket 38280
     2244         */
     2245        public function test_wp_get_term_count_for_object_type_multiple_object_types() {
     2246                register_post_type( 'wptests_cpt' );
     2247                register_taxonomy_for_object_type( 'category', 'wptests_cpt' );
     2248
     2249                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2250                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2251                $custom_post_id = self::factory()->post->create( array( 'post_type' => 'wptests_cpt' ) );
     2252
     2253                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2254                $this->assertEquals( 0,  wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2255        $this->assertEmpty( get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2256
     2257                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2258
     2259                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2260                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2261                $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2262
     2263                wp_set_object_terms( $custom_post_id, array( $term_id ), 'category' );
     2264
     2265                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2266                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2267        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2268
     2269                $term_object = get_term( $term_id, 'category' );
     2270                $this->assertEquals( 2, $term_object->count );
     2271
     2272                wp_remove_object_terms( $custom_post_id, array( $term_id ), 'category' );
     2273
     2274                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2275                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2276        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2277
     2278                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2279
     2280                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2281                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2282        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2283    }
     2284
     2285        /**
     2286         * @ticket 38280
     2287         */
     2288        public function test_wp_get_term_count_for_object_type_multiple_object_types_attachment() {
     2289                register_taxonomy_for_object_type( 'category', 'attachment' );
     2290
     2291                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2292                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2293                $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/canola.jpg', $post_id );
     2294
     2295                $this->assertEmpty( wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2296                $this->assertEmpty( wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2297        $this->assertEmpty( get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2298
     2299                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2300
     2301                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2302                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2303        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2304
     2305                wp_set_object_terms( $attachment_id, array( $term_id ), 'category' );
     2306
     2307                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2308                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2309        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2310
     2311                $term_object = get_term( $term_id, 'category' );
     2312                $this->assertEquals( 2, $term_object->count );
     2313
     2314                wp_remove_object_terms( $attachment_id, array( $term_id ), 'category' );
     2315
     2316                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2317                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2318
     2319                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2320
     2321                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2322                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2323        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2324        }
     2325
    22222326        public static function maybe_filter_count() {
    22232327                return 'foo';
    22242328        }