Add cache invalidation when updating a term, example: create a category, assign it to a post, edit the category. Currently, the post's term cache is not updated. When updating terms in a given taxonomy, invalidate the object term caches linked to that taxonomy.

Introduce `get_taxonomy_last_changed()`, `set_taxonomy_last_changed()`, and `post_taxonomy_is_fresh()`.

`post_taxonomy_is_fresh()` is only called in `get_object_term_cache()` - at which point the taxonomy's `last_changed` value is checked against the post's `{$taxonomy}_last_changed` value.

`set_taxonomy_last_changed()` is called whenever directory database queries are made that insert new terms or affect existing terms.

Fixes #22526.



git-svn-id: https://develop.svn.wordpress.org/trunk@27101 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Scott Taylor 2014-02-06 01:40:05 +00:00
parent 9b85472ac9
commit e33ef0c6ac
2 changed files with 119 additions and 2 deletions

View File

@ -1876,6 +1876,7 @@ function wp_delete_term( $term, $taxonomy, $args = array() ) {
do_action( 'edit_term_taxonomies', $edit_tt_ids );
$wpdb->update( $wpdb->term_taxonomy, compact( 'parent' ), array( 'parent' => $term_obj->term_id) + compact( 'taxonomy' ) );
do_action( 'edited_term_taxonomies', $edit_tt_ids );
set_taxonomy_last_changed( $taxonomy );
}
$objects = $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $tt_id ) );
@ -1910,6 +1911,7 @@ function wp_delete_term( $term, $taxonomy, $args = array() ) {
$wpdb->delete( $wpdb->terms, array( 'term_id' => $term ) );
clean_term_cache($term, $taxonomy);
set_taxonomy_last_changed( $taxonomy );
do_action( 'delete_term', $term, $tt_id, $taxonomy, $deleted_term );
do_action( "delete_$taxonomy", $term, $tt_id, $deleted_term );
@ -2162,6 +2164,7 @@ function wp_insert_term( $term, $taxonomy, $args = array() ) {
do_action( 'edit_terms', $alias->term_id, $taxonomy );
$wpdb->update($wpdb->terms, compact('term_group'), array('term_id' => $alias->term_id) );
do_action( 'edited_terms', $alias->term_id, $taxonomy );
set_taxonomy_last_changed( $taxonomy );
}
}
@ -2223,6 +2226,7 @@ function wp_insert_term( $term, $taxonomy, $args = array() ) {
$term_id = apply_filters('term_id_filter', $term_id, $tt_id);
clean_term_cache($term_id, $taxonomy);
set_taxonomy_last_changed( $taxonomy );
do_action("created_term", $term_id, $tt_id, $taxonomy);
do_action("created_$taxonomy", $term_id, $tt_id);
@ -2329,6 +2333,7 @@ function wp_set_object_terms($object_id, $terms, $taxonomy, $append = false) {
}
wp_cache_delete( $object_id, $taxonomy . '_relationships' );
set_taxonomy_last_changed( $taxonomy );
do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids);
return $tt_ids;
@ -2407,6 +2412,7 @@ function wp_remove_object_terms( $object_id, $terms, $taxonomy ) {
$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) );
do_action( 'deleted_term_relationships', $object_id, $tt_ids );
wp_update_term_count( $tt_ids, $taxonomy );
set_taxonomy_last_changed( $taxonomy );
return (bool) $deleted;
}
@ -2565,6 +2571,7 @@ function wp_update_term( $term_id, $taxonomy, $args = array() ) {
do_action( 'edit_terms', $alias->term_id, $taxonomy );
$wpdb->update( $wpdb->terms, compact('term_group'), array( 'term_id' => $alias->term_id ) );
do_action( 'edited_terms', $alias->term_id, $taxonomy );
set_taxonomy_last_changed( $taxonomy );
}
}
@ -2600,6 +2607,7 @@ function wp_update_term( $term_id, $taxonomy, $args = array() ) {
$term_id = apply_filters('term_id_filter', $term_id, $tt_id);
clean_term_cache($term_id, $taxonomy);
set_taxonomy_last_changed( $taxonomy );
do_action("edited_term", $term_id, $tt_id, $taxonomy);
do_action("edited_$taxonomy", $term_id, $tt_id);
@ -2738,9 +2746,12 @@ function clean_object_term_cache($object_ids, $object_type) {
$taxonomies = get_object_taxonomies( $object_type );
foreach ( $object_ids as $id )
foreach ( $taxonomies as $taxonomy )
foreach ( $object_ids as $id ) {
foreach ( $taxonomies as $taxonomy ) {
wp_cache_delete($id, "{$taxonomy}_relationships");
set_taxonomy_last_changed( $taxonomy );
}
}
do_action('clean_object_term_cache', $object_ids, $object_type);
}
@ -2800,6 +2811,7 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
}
do_action('clean_term_cache', $ids, $taxonomy);
set_taxonomy_last_changed( $taxonomy );
}
wp_cache_set( 'last_changed', microtime(), 'terms' );
@ -2819,6 +2831,9 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
* @return bool|array Empty array if $terms found, but not $taxonomy. False if nothing is in cache for $taxonomy and $id.
*/
function get_object_term_cache($id, $taxonomy) {
if ( ! post_taxonomy_is_fresh( $id, $taxonomy ) ) {
return false;
}
$cache = wp_cache_get($id, "{$taxonomy}_relationships");
return $cache;
}
@ -3117,6 +3132,7 @@ function _update_post_term_count( $terms, $taxonomy ) {
$wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
do_action( 'edited_term_taxonomy', $term, $taxonomy );
}
set_taxonomy_last_changed( $taxonomy->name );
}
/**
@ -3142,6 +3158,7 @@ function _update_generic_term_count( $terms, $taxonomy ) {
$wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) );
do_action( 'edited_term_taxonomy', $term, $taxonomy );
}
set_taxonomy_last_changed( $taxonomy->name );
}
/**
@ -3469,3 +3486,53 @@ function wp_check_term_hierarchy_for_loops( $parent, $term_id, $taxonomy ) {
return $parent;
}
/**
* Retrieve the 'last_changed' value for the passed taxonomy. Retrieves
* from cache, if present
*
* @since 3.9.0
*
* @param string $taxonomy
* @return int
*/
function get_taxonomy_last_changed( $taxonomy ) {
$last_changed = wp_cache_get( 'last_changed', $taxonomy );
if ( ! $last_changed ) {
$last_changed = microtime();
wp_cache_set( 'last_changed', $last_changed, $taxonomy );
}
return $last_changed;
}
/**
* Reset 'last_changed' for the passed taxonomy
*
* @since 3.9.0
*
* @param string $taxonomy
* @return int
*/
function set_taxonomy_last_changed( $taxonomy ) {
wp_cache_delete( 'last_changed', $taxonomy );
return get_taxonomy_last_changed( $taxonomy );
}
/**
* Determine if a post's cache for the passed taxonomy
* is in sync.
* @since 3.9.0
*
* @param int $id
* @param string $taxonomy
* @return boolean
*/
function post_taxonomy_is_fresh( $id, $taxonomy ) {
$last_changed = get_taxonomy_last_changed( $taxonomy );
$post_last_changed = wp_cache_get( $id, $taxonomy . '_last_changed' );
if ( ! $post_last_changed || $last_changed !== $post_last_changed ) {
wp_cache_set( $id, $last_changed, $taxonomy . '_last_changed' );
return false;
}
return true;
}

View File

@ -568,6 +568,56 @@ class Tests_Term extends WP_UnitTestCase {
$this->assertEquals( 0, $count );
}
/**
* @ticket 22526
*/
function test_get_taxonomy_last_changed() {
$last_changed = get_taxonomy_last_changed( 'category' );
$last_changed_cache = wp_cache_get( 'last_changed', 'category' );
$this->assertEquals( $last_changed, $last_changed_cache );
wp_cache_delete( 'last_changed', 'category' );
$this->assertEquals( $last_changed, $last_changed_cache );
$last_changed = get_taxonomy_last_changed( 'category' );
$this->assertNotEquals( $last_changed, $last_changed_cache );
$last_changed2 = get_taxonomy_last_changed( 'category' );
$this->factory->category->create();
$last_changed3 = get_taxonomy_last_changed( 'category' );
$this->assertNotEquals( $last_changed2, $last_changed3 );
}
/**
* @ticket 22526
*/
function test_set_taxonomy_last_changed() {
$last_changed1 = set_taxonomy_last_changed( 'category' );
$last_changed2 = set_taxonomy_last_changed( 'category' );
$this->assertNotEquals( $last_changed1, $last_changed2 );
$last_changed3 = set_taxonomy_last_changed( 'category' );
$last_changed4 = get_taxonomy_last_changed( 'category' );
$this->assertEquals( $last_changed3, $last_changed4 );
}
/**
* @ticket 22526
*/
function test_post_taxonomy_is_fresh() {
$post_id = $this->factory->post->create();
$term_id = $this->factory->category->create( array( 'name' => 'Foo' ) );
wp_set_post_categories( $post_id, $term_id );
$this->assertFalse( post_taxonomy_is_fresh( $post_id, 'category' ) );
$this->assertTrue( post_taxonomy_is_fresh( $post_id, 'category' ) );
$this->assertTrue( post_taxonomy_is_fresh( $post_id, 'category' ) );
wp_update_term( $term_id, 'category', array( 'name' => 'Bar' ) );
$this->assertFalse( post_taxonomy_is_fresh( $post_id, 'category' ) );
get_the_category( $post_id );
$this->assertTrue( post_taxonomy_is_fresh( $post_id, 'category' ) );
}
/**
* @ticket 22526
*/