Store only term IDs in object term relationships caches.

Previously, objects containing all data about a term were stored in each
object's term cache. Besides being wasteful, this approach caused invalidation
issues, as when a modified term count required a flush for all objects
belonging to the term.

Backward compatibility is maintained for plugins that continue to put object
data directly into the `{$taxonomy}_relationships` cache bucket.

Fixes #36814.
Built from https://develop.svn.wordpress.org/trunk@37573


git-svn-id: http://core.svn.wordpress.org/trunk@37541 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Boone Gorges 2016-05-26 04:50:27 +00:00
parent df0c758e22
commit 253686fae6
5 changed files with 65 additions and 18 deletions

View File

@ -242,7 +242,7 @@ function get_terms_to_edit( $post_id, $taxonomy = 'post_tag' ) {
$terms = get_object_term_cache( $post_id, $taxonomy );
if ( false === $terms ) {
$terms = wp_get_object_terms( $post_id, $taxonomy );
wp_cache_add( $post_id, $terms, $taxonomy . '_relationships' );
wp_cache_add( $post_id, wp_list_pluck( $terms, 'term_id' ), $taxonomy . '_relationships' );
}
if ( ! $terms ) {

View File

@ -311,7 +311,7 @@ function get_inline_data($post) {
$terms = get_object_term_cache( $post->ID, $taxonomy_name );
if ( false === $terms ) {
$terms = wp_get_object_terms( $post->ID, $taxonomy_name );
wp_cache_add( $post->ID, $terms, $taxonomy_name . '_relationships' );
wp_cache_add( $post->ID, wp_list_pluck( $terms, 'term_id' ), $taxonomy_name . '_relationships' );
}
$term_ids = empty( $terms ) ? array() : wp_list_pluck( $terms, 'term_id' );

View File

@ -1187,18 +1187,11 @@ function get_the_terms( $post, $taxonomy ) {
if ( false === $terms ) {
$terms = wp_get_object_terms( $post->ID, $taxonomy );
if ( ! is_wp_error( $terms ) ) {
$to_cache = array();
foreach ( $terms as $key => $term ) {
$to_cache[ $key ] = $term->data;
}
wp_cache_add( $post->ID, $to_cache, $taxonomy . '_relationships' );
$term_ids = wp_list_pluck( $terms, 'term_id' );
wp_cache_add( $post->ID, $term_ids, $taxonomy . '_relationships' );
}
}
if ( ! is_wp_error( $terms ) ) {
$terms = array_map( 'get_term', $terms );
}
/**
* Filters the list of terms attached to the given post.
*

View File

@ -3239,15 +3239,42 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
/**
* Retrieves the taxonomy relationship to the term object id.
*
* Upstream functions (like `get_the_terms()` and `is_object_in_term()`) are responsible for populating the
* object-term relationship cache. The current function only fetches relationship data that is already in the cache.
*
* @since 2.3.0
*
* @param int $id Term object ID.
* @param string $taxonomy Taxonomy name.
* @return bool|mixed Empty array if $terms found, but not `$taxonomy`. False if nothing is in cache
* for `$taxonomy` and `$id`.
* @return bool|array Array of `WP_Term` objects, if cached False if cache is empty for `$taxonomy` and `$id`.
*/
function get_object_term_cache( $id, $taxonomy ) {
return wp_cache_get( $id, "{$taxonomy}_relationships" );
$_term_ids = wp_cache_get( $id, "{$taxonomy}_relationships" );
// We leave the priming of relationship caches to upstream functions.
if ( false === $_term_ids ) {
return false;
}
// Backward compatibility for if a plugin is putting objects into the cache, rather than IDs.
$term_ids = array();
foreach ( $_term_ids as $term_id ) {
if ( is_numeric( $term_id ) ) {
$term_ids[] = intval( $term_id );
} elseif ( isset( $term_id->term_id ) ) {
$term_ids[] = intval( $term_id->term_id );
}
}
// Fill the term objects.
_prime_term_caches( $term_ids );
$terms = array();
foreach ( $term_ids as $term_id ) {
$terms[] = wp_cache_get( $term_id, 'terms' );
}
return array_map( 'get_term', $terms );
}
/**
@ -3297,8 +3324,9 @@ function update_object_term_cache($object_ids, $object_type) {
) );
$object_terms = array();
foreach ( (array) $terms as $term )
$object_terms[$term->object_id][$term->taxonomy][] = $term;
foreach ( (array) $terms as $term ) {
$object_terms[ $term->object_id ][ $term->taxonomy ][] = $term->term_id;
}
foreach ( $ids as $id ) {
foreach ( $taxonomies as $taxonomy ) {
@ -3504,6 +3532,32 @@ function _pad_term_counts( &$terms, $taxonomy ) {
$terms_by_id[$id]->count = count($items);
}
/**
* Adds any terms from the given IDs to the cache that do not already exist in cache.
*
* @since 4.6.0
* @access private
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param array $term_ids Array of term IDs.
* @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true.
*/
function _prime_term_caches( $term_ids, $update_meta_cache = true ) {
global $wpdb;
$non_cached_ids = _get_non_cached_ids( $term_ids, 'terms' );
if ( ! empty( $non_cached_ids ) ) {
$fresh_terms = $wpdb->get_results( sprintf( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id IN (%s)", join( ",", array_map( 'intval', $non_cached_ids ) ) ) );
update_term_cache( $fresh_terms, $update_meta_cache );
if ( $update_meta_cache ) {
update_termmeta_cache( $non_cached_ids );
}
}
}
//
// Default callbacks
//
@ -4211,7 +4265,7 @@ function is_object_in_term( $object_id, $taxonomy, $terms = null ) {
$object_terms = get_object_term_cache( $object_id, $taxonomy );
if ( false === $object_terms ) {
$object_terms = wp_get_object_terms( $object_id, $taxonomy, array( 'update_term_meta_cache' => false ) );
wp_cache_set( $object_id, $object_terms, "{$taxonomy}_relationships" );
wp_cache_set( $object_id, wp_list_pluck( $object_terms, 'term_id' ), "{$taxonomy}_relationships" );
}
if ( is_wp_error( $object_terms ) )

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.6-alpha-37572';
$wp_version = '4.6-alpha-37573';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.