Make WordPress Core

Ticket #38280: 38280.8.diff

File 38280.8.diff, 11.4 KB (added by ivankristianto, 5 years ago)

term_taxonomy_id could be different than term_id in term_relationships table. this patch fix it

  • src/wp-includes/taxonomy.php

     
    30913091        return true;
    30923092}
    30933093
     3094/**
     3095 * Retrieves the term count for a specific object type.
     3096 *
     3097 * @since 4.9.0
     3098 *
     3099 * @param int    $term_id     Term ID.
     3100 * @param string $taxonomy    Taxonomy name.
     3101 * @param string $object_type Object type.
     3102 *
     3103 * @return WP_Error|bool|int WP_Error if invalid taxonomy is passed.
     3104 *                           False if object is not in taxonomy.
     3105 *                           Object term count otherwise.
     3106 */
     3107function wp_get_term_count_for_object_type( $term_id, $taxonomy, $object_type ) {
     3108        if ( ! taxonomy_exists( $taxonomy ) ) {
     3109                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
     3110        }
     3111
     3112        if ( ! is_object_in_taxonomy( $object_type, $taxonomy ) ) {
     3113                return false;
     3114        }
     3115
     3116        $term = get_term( $term_id, $taxonomy );
     3117
     3118        if ( 0 === $term->count ) {
     3119                return 0;
     3120        }
     3121
     3122        $taxonomy_object = get_taxonomy( $taxonomy );
     3123
     3124        if ( 1 >= count( $taxonomy_object->object_type ) ) {
     3125                return $term->count;
     3126        }
     3127
     3128        $term_object_count = get_term_meta( $term_id, '_wp_object_count_' . $object_type, true );
     3129        if ( $term_object_count ) {
     3130                return (int) $term_object_count;
     3131        }
     3132
     3133        $counted_object_types = (array) get_term_meta( $term_id, '_wp_counted_object_types', true );
     3134
     3135        /*
     3136         * If the object type has been counted, and other counts exist in meta, we can
     3137         * assume this term has 0 relationships for this object type.
     3138         */
     3139        if ( in_array( $object_type, $counted_object_types, true ) ) {
     3140                foreach ( $taxonomy_object->object_type as $type ) {
     3141                        if ( $test_meta = get_term_meta( $term_id, '_wp_object_count_' . $type, true ) ) {
     3142                                return 0;
     3143                        }
     3144                }
     3145        }
     3146
     3147        // No other meta caches existed. Count and try again.
     3148        if ( wp_update_term_count_now( array( $term_id ), $taxonomy ) ) {
     3149                return wp_get_term_count_for_object_type( $term_id, $taxonomy, $object_type );
     3150        }
     3151}
     3152
    30943153//
    30953154// Cache
    30963155//
     
    36343693        foreach ( (array) $terms as $term ) {
    36353694                $count = 0;
    36363695
     3696                // Remove previous counts to prevent stale data if an object type is removed from a taxonomy.
     3697                $counted_object_types = (array) get_term_meta( $term, '_wp_counted_object_types', true );
     3698
     3699                foreach ( $counted_object_types as $o_type ) {
     3700                        delete_term_meta( $term, '_wp_object_count_' . $o_type );
     3701                }
     3702
     3703                delete_term_meta( $term, '_wp_counted_object_types' );
     3704
     3705                $term_count_meta = array();
     3706
     3707                $term_taxonomy_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE term_id = %d", $term ) );
     3708
     3709                if ( $object_types ) {
     3710                        foreach ( $object_types as $type ) {
     3711                                $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_taxonomy_id ) );
     3712
     3713                                $count += $current_count;
     3714                                $term_count_meta[ $type ] = $current_count;
     3715                        }
     3716                }
     3717
    36373718                // Attachments can be 'inherit' status, we need to base count off the parent's status if so.
    36383719                if ( $check_attachments ) {
    3639                         $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 ) );
     3720                        $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_taxonomy_id ) );
     3721
     3722                        $count += $attachment_count;
     3723                        $term_count_meta['attachment'] = $attachment_count;
     3724
     3725                        // Re-add attachment so the meta gets saved below.
     3726                        $object_types[] = 'attachment';
    36403727                }
    36413728
    3642                 if ( $object_types ) {
    3643                         $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 ) );
     3729                // Save individual counts for each object type in term meta.
     3730                if ( 1 < count( $term_count_meta ) ) {
     3731                        foreach ( $object_types as $type ) {
     3732                                if ( ! empty( $term_count_meta[ $type ] ) ) {
     3733                                        update_term_meta( $term, '_wp_object_count_' . $type, (int) $term_count_meta[ $type ] );
     3734                                }
     3735                        }
     3736
     3737                        update_term_meta( $term, '_wp_counted_object_types', $object_types );
     3738                } else {
     3739                        foreach ( $object_types as $type ) {
     3740                                delete_term_meta( $term, '_wp_object_count_' . $type );
     3741                        }
     3742
     3743                        delete_term_meta( $term, '_wp_counted_object_types' );
    36443744                }
    36453745
    36463746                /** This action is documented in wp-includes/taxonomy.php */
    36473747                do_action( 'edit_term_taxonomy', $term, $taxonomy->name );
    3648                 $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
     3748                $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term_taxonomy_id ) );
    36493749
    36503750                /** This action is documented in wp-includes/taxonomy.php */
    36513751                do_action( 'edited_term_taxonomy', $term, $taxonomy->name );
  • tests/phpunit/tests/term/getTerms.php

     
    27762776                $this->assertNotEquals( 'foo', $found );
    27772777        }
    27782778
     2779        /**
     2780         * @ticket 38280
     2781         */
     2782        public function test_wp_get_term_count_for_object_type_single_object_type() {
     2783                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2784                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2785
     2786                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2787
     2788                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2789        $this->assertFalse( (bool) get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2790
     2791                $term_object = get_term( $term_id, 'category' );
     2792                $this->assertEquals( 1, $term_object->count );
     2793
     2794                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2795
     2796                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2797        }
     2798
     2799        /**
     2800         * @ticket 38280
     2801         */
     2802        public function test_wp_get_term_count_for_object_type_multiple_object_types() {
     2803                register_post_type( 'wptests_cpt' );
     2804                register_taxonomy_for_object_type( 'category', 'wptests_cpt' );
     2805
     2806                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2807                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2808                $custom_post_id = self::factory()->post->create( array( 'post_type' => 'wptests_cpt' ) );
     2809
     2810                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2811                $this->assertEquals( 0,  wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2812        $this->assertEmpty( get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2813
     2814                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2815
     2816                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2817                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2818                $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2819
     2820                wp_set_object_terms( $custom_post_id, array( $term_id ), 'category' );
     2821
     2822                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2823                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2824        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2825
     2826                $term_object = get_term( $term_id, 'category' );
     2827                $this->assertEquals( 2, $term_object->count );
     2828
     2829                wp_remove_object_terms( $custom_post_id, array( $term_id ), 'category' );
     2830
     2831                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2832                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2833        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2834
     2835                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2836
     2837                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2838                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'wptests_cpt' ) );
     2839        $this->assertEquals( array( 'post', 'wptests_cpt' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2840    }
     2841
     2842        /**
     2843         * @ticket 38280
     2844         */
     2845        public function test_wp_get_term_count_for_object_type_multiple_object_types_attachment() {
     2846                register_taxonomy_for_object_type( 'category', 'attachment' );
     2847
     2848                $term_id = self::factory()->term->create( array( 'taxonomy' => 'category' ) );
     2849                $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) );
     2850                $attachment_id = self::factory()->attachment->create_upload_object( DIR_TESTDATA . '/images/canola.jpg', $post_id );
     2851
     2852                $this->assertEmpty( wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2853                $this->assertEmpty( wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2854        $this->assertEmpty( get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2855
     2856                wp_set_object_terms( $post_id, array( $term_id ), 'category' );
     2857
     2858                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2859                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2860        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2861
     2862                wp_set_object_terms( $attachment_id, array( $term_id ), 'category' );
     2863
     2864                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2865                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2866        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2867
     2868                $term_object = get_term( $term_id, 'category' );
     2869                $this->assertEquals( 2, $term_object->count );
     2870
     2871                wp_remove_object_terms( $attachment_id, array( $term_id ), 'category' );
     2872
     2873                $this->assertEquals( 1, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2874                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2875
     2876                wp_remove_object_terms( $post_id, array( $term_id ), 'category' );
     2877
     2878                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'post' ) );
     2879                $this->assertEquals( 0, wp_get_term_count_for_object_type( $term_id, 'category', 'attachment' ) );
     2880        $this->assertEquals( array( 'post', 'attachment' ), get_term_meta( $term_id, '_wp_counted_object_types', true ) );
     2881        }
     2882
    27792883        public static function maybe_filter_count() {
    27802884                return 'foo';
    27812885        }