Changeset 36566
- Timestamp:
- 02/17/2016 10:57:33 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/comment-template.php
r36527 r36566 1393 1393 */ 1394 1394 $wp_query->comments = apply_filters( 'comments_array', $comments_flat, $post->ID ); 1395 1396 // Set up lazy-loading for comment metadata.1397 add_action( 'get_comment_metadata', array( $wp_query, 'lazyload_comment_meta' ), 10, 2 );1398 1395 1399 1396 $comments = &$wp_query->comments; … … 2030 2027 if ( null === $r['reverse_top_level'] ) 2031 2028 $r['reverse_top_level'] = ( 'desc' == get_option('comment_order') ); 2029 2030 wp_queue_comments_for_comment_meta_lazyload( $_comments ); 2032 2031 2033 2032 if ( empty( $r['walker'] ) ) { -
trunk/src/wp-includes/comment.php
r36542 r36566 470 470 471 471 /** 472 * Queue comments for metadata lazyloading. 473 * 474 * @since 4.5.0 475 * 476 * @param array $comments Array of comment objects. 477 */ 478 function wp_queue_comments_for_comment_meta_lazyload( $comments ) { 479 // Don't use `wp_list_pluck()` to avoid by-reference manipulation. 480 $comment_ids = array(); 481 if ( is_array( $comments ) ) { 482 foreach ( $comments as $comment ) { 483 if ( $comment instanceof WP_Comment ) { 484 $comment_ids[] = $comment->comment_ID; 485 } 486 } 487 } 488 489 if ( $comment_ids ) { 490 $lazyloader = wp_metadata_lazyloader(); 491 $lazyloader->queue_objects( 'comment', $comment_ids ); 492 } 493 } 494 495 /** 472 496 * Sets the cookies used to store an unauthenticated commentator's identity. Typically used 473 497 * to recall previous comments by this commentator that are still held in moderation. -
trunk/src/wp-includes/meta.php
r36511 r36566 853 853 854 854 /** 855 * Get the metadata lazyloading queue. 856 * 857 * @since 4.5.0 858 * 859 * @return WP_Metadata_Lazyloader $lazyloader Metadata lazyloader queue. 860 */ 861 function wp_metadata_lazyloader() { 862 static $wp_metadata_lazyloader; 863 864 if ( null === $wp_metadata_lazyloader ) { 865 $wp_metadata_lazyloader = new WP_Metadata_Lazyloader(); 866 } 867 868 return $wp_metadata_lazyloader; 869 } 870 871 /** 855 872 * Given a meta query, generates SQL clauses to be appended to a main query. 856 873 * -
trunk/src/wp-includes/post.php
r36498 r36566 5949 5949 5950 5950 /** 5951 * Queue posts for lazyloading of term meta. 5952 * 5953 * @since 4.5.0 5954 * 5955 * @param array $posts Array of WP_Post objects. 5956 */ 5957 function wp_queue_posts_for_term_meta_lazyload( $posts ) { 5958 $post_type_taxonomies = $term_ids = array(); 5959 foreach ( $posts as $post ) { 5960 if ( ! ( $post instanceof WP_Post ) ) { 5961 continue; 5962 } 5963 5964 if ( ! isset( $post_type_taxonomies[ $post->post_type ] ) ) { 5965 $post_type_taxonomies[ $post->post_type ] = get_object_taxonomies( $post->post_type ); 5966 } 5967 5968 foreach ( $post_type_taxonomies[ $post->post_type ] as $taxonomy ) { 5969 // Term cache should already be primed by `update_post_term_cache()`. 5970 $terms = get_object_term_cache( $post->ID, $taxonomy ); 5971 if ( false !== $terms ) { 5972 foreach ( $terms as $term ) { 5973 if ( ! isset( $term_ids[ $term->term_id ] ) ) { 5974 $term_ids[] = $term->term_id; 5975 } 5976 } 5977 } 5978 } 5979 } 5980 5981 if ( $term_ids ) { 5982 $lazyloader = wp_metadata_lazyloader(); 5983 $lazyloader->queue_objects( 'term', $term_ids ); 5984 } 5985 } 5986 5987 /** 5951 5988 * Update the custom taxonomies' term counts when a post's status is changed. 5952 5989 * -
trunk/src/wp-includes/query.php
r36524 r36566 3606 3606 $this->posts = array_map( 'get_post', $this->posts ); 3607 3607 3608 3609 if ( $q['update_post_term_cache'] ) {3610 add_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ), 10, 2 );3611 }3612 3613 3608 if ( ! $q['suppress_filters'] ) { 3614 3609 /** … … 3739 3734 // If comments have been fetched as part of the query, make sure comment meta lazy-loading is set up. 3740 3735 if ( ! empty( $this->comments ) ) { 3741 add_filter( 'get_comment_metadata', array( $this, 'lazyload_comment_meta' ), 10, 2);3736 wp_queue_comments_for_comment_meta_lazyload( $this->comments ); 3742 3737 } 3743 3738 … … 3769 3764 $this->post_count = 0; 3770 3765 $this->posts = array(); 3766 } 3767 3768 if ( $q['update_post_term_cache'] ) { 3769 wp_queue_posts_for_term_meta_lazyload( $this->posts ); 3771 3770 } 3772 3771 … … 4835 4834 4836 4835 /** 4837 * Lazy-loads termmeta for located posts. 4838 * 4839 * As a rule, term queries (`get_terms()` and `wp_get_object_terms()`) prime the metadata cache for matched 4840 * terms by default. However, this can cause a slight performance penalty, especially when that metadata is 4841 * not actually used. In the context of a `WP_Query` instance, we're able to avoid this potential penalty. 4842 * `update_object_term_cache()`, called from `update_post_caches()`, does not 'update_term_meta_cache'. 4843 * Instead, the first time `get_term_meta()` is called from within a `WP_Query` loop, the current method 4844 * detects the fact, and then primes the metadata cache for all terms attached to all posts in the loop, 4845 * with a single database query. 4846 * 4847 * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it 4848 * directly, from either inside or outside the `WP_Query` object. 4836 * Lazyload term meta for posts in the loop. 4849 4837 * 4850 4838 * @since 4.4.0 4851 * @access public 4852 * 4853 * @param mixed $check The `$check` param passed from the 'get_term_metadata' hook. 4854 * @param int $term_id ID of the term whose metadata is being cached. 4855 * @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be 4856 * another value if filtered by a plugin. 4839 * @deprecated 4.5.0 See wp_queue_posts_for_term_meta_lazyload(). 4840 * 4841 * @param mixed $check 4842 * @param int $term_id 4843 * @return mixed 4857 4844 */ 4858 4845 public function lazyload_term_meta( $check, $term_id ) { 4859 // We can only lazyload if the entire post object is present. 4860 $posts = array(); 4861 foreach ( $this->posts as $post ) { 4862 if ( $post instanceof WP_Post ) { 4863 $posts[] = $post; 4864 } 4865 } 4866 4867 if ( ! empty( $posts ) ) { 4868 // Fetch cached term_ids for each post. Keyed by term_id for faster lookup. 4869 $term_ids = array(); 4870 foreach ( $posts as $post ) { 4871 $taxonomies = get_object_taxonomies( $post->post_type ); 4872 foreach ( $taxonomies as $taxonomy ) { 4873 // Term cache should already be primed by 'update_post_term_cache'. 4874 $terms = get_object_term_cache( $post->ID, $taxonomy ); 4875 if ( false !== $terms ) { 4876 foreach ( $terms as $term ) { 4877 if ( ! isset( $term_ids[ $term->term_id ] ) ) { 4878 $term_ids[ $term->term_id ] = 1; 4879 } 4880 } 4881 } 4882 } 4883 } 4884 4885 /* 4886 * Only update the metadata cache for terms belonging to these posts if the term_id passed 4887 * to `get_term_meta()` matches one of those terms. This prevents a single call to 4888 * `get_term_meta()` from priming metadata for all `WP_Query` objects. 4889 */ 4890 if ( isset( $term_ids[ $term_id ] ) ) { 4891 update_termmeta_cache( array_keys( $term_ids ) ); 4892 remove_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ), 10, 2 ); 4893 } 4894 } 4895 4896 // If no terms were found, there's no need to run this again. 4897 if ( empty( $term_ids ) ) { 4898 remove_filter( 'get_term_metadata', array( $this, 'lazyload_term_meta' ), 10, 2 ); 4899 } 4900 4846 _deprecated_function( __METHOD__, '4.5.0' ); 4901 4847 return $check; 4902 4848 } 4903 4849 4904 4850 /** 4905 * Lazy-load comment meta when inside of a `WP_Query` loop. 4906 * 4907 * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it 4908 * directly, from either inside or outside the `WP_Query` object. 4851 * Lazyload comment meta for comments in the loop. 4909 4852 * 4910 4853 * @since 4.4.0 4911 * 4912 * @param mixed $check The `$check` param passed from the 'get_comment_metadata' hook. 4913 * @param int $comment_id ID of the comment whose metadata is being cached. 4914 * @return mixed The original value of `$check`, to not affect 'get_comment_metadata'. 4854 * @deprecated 4.5.0 See wp_queue_comments_for_comment_meta_lazyload(). 4855 * 4856 * @param mixed $check 4857 * @param int $comment_id 4858 * @return mixed 4915 4859 */ 4916 4860 public function lazyload_comment_meta( $check, $comment_id ) { 4917 // Don't use `wp_list_pluck()` to avoid by-reference manipulation. 4918 $comment_ids = array(); 4919 if ( is_array( $this->comments ) ) { 4920 foreach ( $this->comments as $comment ) { 4921 $comment_ids[] = $comment->comment_ID; 4922 } 4923 } 4924 4925 /* 4926 * Only update the metadata cache for comments belonging to these posts if the comment_id passed 4927 * to `get_comment_meta()` matches one of those comments. This prevents a single call to 4928 * `get_comment_meta()` from priming metadata for all `WP_Query` objects. 4929 */ 4930 if ( in_array( $comment_id, $comment_ids ) ) { 4931 update_meta_cache( 'comment', $comment_ids ); 4932 remove_filter( 'get_comment_metadata', array( $this, 'lazyload_comment_meta' ), 10, 2 ); 4933 } elseif ( empty( $comment_ids ) ) { 4934 remove_filter( 'get_comment_metadata', array( $this, 'lazyload_comment_meta' ), 10, 2 ); 4935 } 4936 4861 _deprecated_function( __METHOD__, '4.5.0' ); 4937 4862 return $check; 4938 4863 } -
trunk/src/wp-settings.php
r36557 r36566 136 136 require( ABSPATH . WPINC . '/meta.php' ); 137 137 require( ABSPATH . WPINC . '/class-wp-meta-query.php' ); 138 require( ABSPATH . WPINC . '/class-wp-metadata-lazyloader.php' ); 138 139 require( ABSPATH . WPINC . '/general-template.php' ); 139 140 require( ABSPATH . WPINC . '/link-template.php' ); -
trunk/tests/phpunit/tests/term/meta.php
r35585 r36566 135 135 $num_queries = $wpdb->num_queries; 136 136 $this->assertSame( 'bar', get_term_meta( $terms[0], 'foo', true ) ); 137 $this->assertSame( $num_queries + 1, $wpdb->num_queries ); 137 $num_queries++; 138 $this->assertSame( $num_queries, $wpdb->num_queries ); 138 139 139 140 // Second and third requests should be in cache. 140 141 $this->assertSame( 'bar', get_term_meta( $terms[1], 'foo', true ) ); 141 142 $this->assertSame( 'bar', get_term_meta( $terms[2], 'foo', true ) ); 142 $this->assertSame( $num_queries + 1, $wpdb->num_queries );143 $this->assertSame( $num_queries, $wpdb->num_queries ); 143 144 144 145 // Querying a term not primed should result in a hit. 146 $num_queries++; 145 147 $this->assertSame( 'bar', get_term_meta( $orphan_term, 'foo', true ) ); 146 $this->assertSame( $num_queries + 2, $wpdb->num_queries );148 $this->assertSame( $num_queries, $wpdb->num_queries ); 147 149 } 148 150 } 149 151 } 150 152 151 /** 152 * @ticket 34073 153 */ 154 public function test_term_meta_should_be_lazy_loaded_only_for_the_queries_in_which_the_term_has_posts() { 155 global $wpdb; 156 157 $posts = self::factory()->post->create_many( 3, array( 'post_status' => 'publish' ) ); 158 register_taxonomy( 'wptests_tax', 'post' ); 159 $terms = self::factory()->term->create_many( 6, array( 'taxonomy' => 'wptests_tax' ) ); 160 161 wp_set_object_terms( $posts[0], array( $terms[0], $terms[1] ), 'wptests_tax' ); 162 wp_set_object_terms( $posts[1], array( $terms[2], $terms[3] ), 'wptests_tax' ); 163 wp_set_object_terms( $posts[2], array( $terms[0], $terms[4], $terms[5] ), 'wptests_tax' ); 164 165 foreach ( $terms as $t ) { 166 add_term_meta( $t, 'foo', 'bar' ); 167 } 168 169 $q0 = new WP_Query( array( 'p' => $posts[0], 'cache_results' => true ) ); 170 $q1 = new WP_Query( array( 'p' => $posts[1], 'cache_results' => true ) ); 171 $q2 = new WP_Query( array( 'p' => $posts[2], 'cache_results' => true ) ); 172 173 /* 174 * $terms[0] belongs to both $posts[0] and $posts[2], so `get_term_meta( $terms[0] )` should prime 175 * the cache for term matched by $q0 and $q2. 176 */ 177 178 // First request will hit the database. 179 $num_queries = $wpdb->num_queries; 180 181 // Prime caches. 182 $this->assertSame( 'bar', get_term_meta( $terms[0], 'foo', true ) ); 183 184 // Two queries: one for $q0 and one for $q2. 185 $num_queries += 2; 186 $this->assertSame( $num_queries, $wpdb->num_queries ); 187 188 // Next requests should be in cache. 189 $this->assertSame( 'bar', get_term_meta( $terms[1], 'foo', true ) ); 190 $this->assertSame( 'bar', get_term_meta( $terms[4], 'foo', true ) ); 191 $this->assertSame( 'bar', get_term_meta( $terms[5], 'foo', true ) ); 192 $this->assertSame( $num_queries, $wpdb->num_queries ); 193 194 // Querying for $terms[2] will prime $terms[3] as well. 195 $this->assertSame( 'bar', get_term_meta( $terms[2], 'foo', true ) ); 196 $num_queries++; 197 $this->assertSame( $num_queries, $wpdb->num_queries ); 198 199 $this->assertSame( 'bar', get_term_meta( $terms[3], 'foo', true ) ); 200 $this->assertSame( $num_queries, $wpdb->num_queries ); 201 } 202 203 public function test_adding_term_meta_should_bust_get_terms_cache() { 153 public function test_updating_term_meta_should_bust_get_terms_cache() { 204 154 $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) ); 205 155 206 156 add_term_meta( $terms[0], 'foo', 'bar' ); 157 add_term_meta( $terms[1], 'foo', 'baz' ); 207 158 208 159 // Prime cache. … … 220 171 $this->assertEqualSets( array( $terms[0] ), $found ); 221 172 222 add_term_meta( $terms[1], 'foo', 'bar' );173 update_term_meta( $terms[1], 'foo', 'bar' ); 223 174 224 175 $found = get_terms( 'wptests_tax', array( … … 236 187 } 237 188 238 public function test_ updating_term_meta_should_bust_get_terms_cache() {189 public function test_deleting_term_meta_should_bust_get_terms_cache() { 239 190 $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) ); 240 191 241 192 add_term_meta( $terms[0], 'foo', 'bar' ); 242 add_term_meta( $terms[1], 'foo', 'ba z' );193 add_term_meta( $terms[1], 'foo', 'bar' ); 243 194 244 195 // Prime cache. … … 254 205 ) ); 255 206 256 $this->assertEqualSets( array( $terms[0] ), $found );257 258 update_term_meta( $terms[1], 'foo', 'bar' );207 $this->assertEqualSets( array( $terms[0], $terms[1] ), $found ); 208 209 delete_term_meta( $terms[1], 'foo', 'bar' ); 259 210 260 211 $found = get_terms( 'wptests_tax', array( … … 269 220 ) ); 270 221 271 $this->assertEqualSets( array( $terms[0], $terms[1] ), $found );272 }273 274 public function test_deleting_term_meta_should_bust_get_terms_cache() {275 $terms = self::factory()->term->create_many( 2, array( 'taxonomy' => 'wptests_tax' ) );276 277 add_term_meta( $terms[0], 'foo', 'bar' );278 add_term_meta( $terms[1], 'foo', 'bar' );279 280 // Prime cache.281 $found = get_terms( 'wptests_tax', array(282 'hide_empty' => false,283 'fields' => 'ids',284 'meta_query' => array(285 array(286 'key' => 'foo',287 'value' => 'bar',288 ),289 ),290 ) );291 292 $this->assertEqualSets( array( $terms[0], $terms[1] ), $found );293 294 delete_term_meta( $terms[1], 'foo', 'bar' );295 296 $found = get_terms( 'wptests_tax', array(297 'hide_empty' => false,298 'fields' => 'ids',299 'meta_query' => array(300 array(301 'key' => 'foo',302 'value' => 'bar',303 ),304 ),305 ) );306 307 222 $this->assertEqualSets( array( $terms[0] ), $found ); 308 223 }
Note: See TracChangeset
for help on using the changeset viewer.