From 50a96f165ea6ced49a78e6e78368d45289c34a41 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Thu, 6 Feb 2014 01:58:01 +0000 Subject: [PATCH] Regenerate the term hierarchy cache (`{taxonomy}_children`) when it is out of sync with the passed taxonomy's `last_changed` value. Introduces `taxonomy_hierarchy_is_fresh()`, which is only called in `_get_term_hierarchy()`. The taxonomy's `last_changed` value is checked against the value of `wp_cache_get( 'hierarchy_last_changed', $taxonomy )`. Adds a unit test - `Tests_Term:test_hierachy_invalidation()`. See [27101], which makes this type of cache invalidation possible. Fixes #14485. git-svn-id: https://develop.svn.wordpress.org/trunk@27102 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/taxonomy.php | 26 +++++++++++++++++++- tests/phpunit/tests/term.php | 47 +++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 297b98d8be..464a00ca3f 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -2948,7 +2948,10 @@ function update_term_cache($terms, $taxonomy = '') { function _get_term_hierarchy($taxonomy) { if ( !is_taxonomy_hierarchical($taxonomy) ) return array(); - $children = get_option("{$taxonomy}_children"); + $children = false; + if ( taxonomy_hierarchy_is_fresh( $taxonomy ) ) { + $children = get_option("{$taxonomy}_children"); + } if ( is_array($children) ) return $children; @@ -3521,6 +3524,7 @@ function set_taxonomy_last_changed( $taxonomy ) { /** * Determine if a post's cache for the passed taxonomy * is in sync. + * * @since 3.9.0 * * @param int $id @@ -3535,4 +3539,24 @@ function post_taxonomy_is_fresh( $id, $taxonomy ) { return false; } return true; +} + +/** + * Determine if a hierarchy's cache for the passed taxonomy + * is in sync. + * + * @since 3.9.0 + * + * @param int $id + * @param string $taxonomy + * @return boolean + */ +function taxonomy_hierarchy_is_fresh( $taxonomy ) { + $last_changed = get_taxonomy_last_changed( $taxonomy ); + $hierarchy_last_changed = wp_cache_get( 'hierarchy_last_changed', $taxonomy ); + if ( ! $hierarchy_last_changed || $last_changed !== $hierarchy_last_changed ) { + wp_cache_set( 'hierarchy_last_changed', $last_changed, $taxonomy ); + return false; + } + return true; } \ No newline at end of file diff --git a/tests/phpunit/tests/term.php b/tests/phpunit/tests/term.php index 5fc16c8d4e..19ffcd0469 100644 --- a/tests/phpunit/tests/term.php +++ b/tests/phpunit/tests/term.php @@ -585,7 +585,7 @@ class Tests_Term extends WP_UnitTestCase { $last_changed3 = get_taxonomy_last_changed( 'category' ); $this->assertNotEquals( $last_changed2, $last_changed3 ); } - + /** * @ticket 22526 */ @@ -634,4 +634,49 @@ class Tests_Term extends WP_UnitTestCase { $cats2 = get_the_category( $post->ID ); $this->assertNotEquals( $term->name, reset( $cats2 )->name ); } + + function test_hierachy_invalidation() { + $tax = 'burrito'; + register_taxonomy( $tax, 'post', array( 'hierarchical' => true ) ); + $this->assertTrue( get_taxonomy( $tax )->hierarchical ); + + $step = 1; + $parent_id = 0; + $children = 0; + + foreach ( range( 1, 99 ) as $i ) { + switch ( $step ) { + case 1: + $parent = wp_insert_term( 'Parent' . $i, $tax ); + $parent_id = $parent['term_id']; + break; + case 2: + $parent = wp_insert_term( 'Child' . $i, $tax, array( 'parent' => $parent_id ) ); + $parent_id = $parent['term_id']; + $children++; + break; + case 3: + wp_insert_term( 'Grandchild' . $i, $tax, array( 'parent' => $parent_id ) ); + $parent_id = 0; + $children++; + break; + } + + $terms = get_terms( $tax, array( 'hide_empty' => false ) ); + $this->assertEquals( $i, count( $terms ) ); + if ( 1 < $i ) { + $hierarchy = _get_term_hierarchy( $tax ); + $this->assertNotEmpty( $hierarchy ); + $this->assertEquals( $children, count( $hierarchy, COUNT_RECURSIVE ) - count( $hierarchy ) ); + } + + if ( $i % 3 === 0 ) { + $step = 1; + } else { + $step++; + } + } + + _unregister_taxonomy( $tax ); + } }