Skip to content

Commit b286316

Browse files
committed
Taxonomy: Avoid unnecessarily recalculating term counts when a post is updated and its status is unchanged.
If the terms of the post are changed then the term recounting is still handled by `wp_update_term_count()` inside `wp_set_object_terms()`. Props pbearne, johnbillion, peterwilsoncc, Chouby Fixes #42522 git-svn-id: https://develop.svn.wordpress.org/trunk@60365 602fd350-edb4-49c9-b593-d223f7449a82
1 parent c42230c commit b286316

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

src/wp-includes/post.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8170,6 +8170,10 @@ function wp_queue_posts_for_term_meta_lazyload( $posts ) {
81708170
* @param WP_Post $post Post object.
81718171
*/
81728172
function _update_term_count_on_transition_post_status( $new_status, $old_status, $post ) {
8173+
if ( $new_status === $old_status ) {
8174+
return;
8175+
}
8176+
81738177
// Update counts for the post's terms.
81748178
foreach ( (array) get_object_taxonomies( $post->post_type ) as $taxonomy ) {
81758179
$tt_ids = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'tt_ids' ) );
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
3+
/**
4+
* Tests for the _update_term_count_on_transition_post_status function.
5+
*
6+
* See Tests_Term_WpSetObjectTerms for tests that cover changing terms on a post when saving it.
7+
*
8+
* @group taxonomy
9+
*
10+
* @covers ::_update_term_count_on_transition_post_status
11+
*/
12+
class Tests_Taxonomy_UpdateTermCountOnTransitionPostStatus extends WP_UnitTestCase {
13+
14+
/**
15+
* @var int Post ID.
16+
*/
17+
protected static $post_id;
18+
19+
/**
20+
* @var int Term ID.
21+
*/
22+
protected static $term_id;
23+
24+
/**
25+
* @var string Post type.
26+
*/
27+
protected static $post_type = 'post';
28+
29+
/**
30+
* @var string Taxonomy name.
31+
*/
32+
protected static $taxonomy = 'category';
33+
34+
/**
35+
* Create shared fixtures.
36+
*/
37+
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
38+
self::$post_id = $factory->post->create(
39+
array(
40+
'post_type' => self::$post_type,
41+
'post_status' => 'publish',
42+
)
43+
);
44+
45+
self::$term_id = $factory->term->create(
46+
array(
47+
'taxonomy' => self::$taxonomy,
48+
'name' => 'Test Category',
49+
)
50+
);
51+
52+
wp_set_object_terms( self::$post_id, self::$term_id, self::$taxonomy );
53+
}
54+
55+
/**
56+
* Test that the term count is updated when a post is published.
57+
*
58+
* @ticket 42522
59+
*/
60+
public function test_update_term_count_on_publish() {
61+
$this->assertTermCount( 1, self::$term_id );
62+
63+
// Change post status to draft.
64+
wp_update_post(
65+
array(
66+
'ID' => self::$post_id,
67+
'post_status' => 'draft',
68+
)
69+
);
70+
71+
$this->assertTermCount( 0, self::$term_id );
72+
73+
// Change post status back to publish.
74+
wp_update_post(
75+
array(
76+
'ID' => self::$post_id,
77+
'post_status' => 'publish',
78+
)
79+
);
80+
81+
$this->assertTermCount( 1, self::$term_id );
82+
}
83+
84+
/**
85+
* Test that the term count is updated when a post is moved to trash.
86+
*
87+
* @ticket 42522
88+
*/
89+
public function test_update_term_count_on_trash() {
90+
$this->assertTermCount( 1, self::$term_id );
91+
92+
// Move post to trash.
93+
wp_trash_post( self::$post_id );
94+
95+
$this->assertTermCount( 0, self::$term_id );
96+
}
97+
98+
/**
99+
* Test that the term count is updated when a post is restored from trash.
100+
*
101+
* @ticket 42522
102+
*/
103+
public function test_update_term_count_on_restore() {
104+
$this->assertTermCount( 1, self::$term_id );
105+
106+
// Move post to trash.
107+
wp_trash_post( self::$post_id );
108+
109+
$this->assertTermCount( 0, self::$term_id, 'Post is in trash.' );
110+
111+
// Restore post from trash.
112+
wp_untrash_post( self::$post_id );
113+
114+
$this->assertTermCount( 0, self::$term_id, 'Post is in draft after untrashing.' );
115+
116+
// re-publish post.
117+
wp_publish_post( self::$post_id );
118+
119+
$this->assertTermCount( 1, self::$term_id, 'Post is in publish after publishing.' );
120+
}
121+
122+
/**
123+
* Test that the term count is updated when a post is deleted permanently.
124+
*
125+
* @ticket 42522
126+
*/
127+
public function test_update_term_count_on_delete() {
128+
$this->assertTermCount( 1, self::$term_id );
129+
130+
// Delete post permanently.
131+
wp_delete_post( self::$post_id, true );
132+
133+
$this->assertTermCount( 0, self::$term_id );
134+
}
135+
136+
/**
137+
* Test that the term count is not recalculated when neither the terms nor the post status change.
138+
*
139+
* @ticket 42522
140+
*/
141+
public function test_term_count_is_not_recalculated_when_status_does_not_change() {
142+
$post_id = self::factory()->post->create(
143+
array(
144+
'post_type' => self::$post_type,
145+
'post_status' => 'publish',
146+
)
147+
);
148+
149+
wp_set_object_terms(
150+
$post_id,
151+
self::$term_id,
152+
self::$taxonomy
153+
);
154+
$edited_term_taxonomy_count = did_action( 'edited_term_taxonomy' );
155+
156+
// Change something about the post but not its status.
157+
wp_update_post(
158+
array(
159+
'ID' => $post_id,
160+
'post_content' => get_post( $post_id )->post_content . ' - updated',
161+
)
162+
);
163+
164+
$this->assertSame( 0, did_action( 'edited_term_taxonomy' ) - $edited_term_taxonomy_count, 'Term taxonomy count should not be recalculated when post status does not change.' );
165+
$this->assertTermCount( 2, self::$term_id );
166+
}
167+
168+
/**
169+
* Assert that the term count is correct.
170+
*
171+
* @since 6.9.0
172+
*
173+
* @param int $expected_count Expected term count.
174+
* @param int $term_id Term ID.
175+
*/
176+
protected function assertTermCount( $expected_count, $term_id, $message = '' ) {
177+
$term = get_term( $term_id );
178+
$this->assertSame( $expected_count, $term->count, $message );
179+
}
180+
}

0 commit comments

Comments
 (0)