From 2d73050edae758b19154089b52890df91df6afdf Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Wed, 19 Feb 2020 03:50:38 +0000 Subject: [PATCH] Posts, Post Types: Discard `tags_input` parameter in `wp_update_post()` if it's the same as existing post tags. This ensures that `wp_update_post()` does not unintentionally modify post tags if the post has several tags with the same name but different slugs. Tags should only be modified if `tags_input` parameter was explicitly provided, and is different from the existing tags. Props kaggdesign, SergeyBiryukov. Fixes #45121. git-svn-id: https://develop.svn.wordpress.org/trunk@47317 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/post.php | 14 +++++++++++ tests/phpunit/tests/post.php | 49 +++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 48fe341655..df2c3b545d 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -4217,6 +4217,20 @@ function wp_update_post( $postarr = array(), $wp_error = false ) { return wp_insert_attachment( $postarr, false, 0, $wp_error ); } + // Discard 'tags_input' parameter if it's the same as existing post tags. + if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $postarr['post_type'], 'post_tag' ) ) { + $tags = get_the_terms( $postarr['ID'], 'post_tag' ); + $tag_names = array(); + + if ( $tags && ! is_wp_error( $tags ) ) { + $tag_names = wp_list_pluck( $tags, 'name' ); + } + + if ( $postarr['tags_input'] === $tag_names ) { + unset( $postarr['tags_input'] ); + } + } + return wp_insert_post( $postarr, $wp_error ); } diff --git a/tests/phpunit/tests/post.php b/tests/phpunit/tests/post.php index 72a08691e6..d4672212cc 100644 --- a/tests/phpunit/tests/post.php +++ b/tests/phpunit/tests/post.php @@ -1118,8 +1118,8 @@ class Tests_Post extends WP_UnitTestCase { } /** - * If a post is sticky and is updated by a user that does not have the publish_post capability, it should _stay_ - * sticky. + * If a post is sticky and is updated by a user that does not have the publish_post capability, + * it should _stay_ sticky. * * @ticket 24153 */ @@ -1156,8 +1156,8 @@ class Tests_Post extends WP_UnitTestCase { } /** - * If the `edit_post()` method is invoked by a user without publish_posts permission, the sticky status of the post - * should not be changed. + * If the `edit_post()` method is invoked by a user without publish_posts permission, + * the sticky status of the post should not be changed. * * @ticket 24153 */ @@ -1426,4 +1426,45 @@ class Tests_Post extends WP_UnitTestCase { $post = get_post( $post_id ); self::assertEquals( strtotime( gmdate( 'Y-m-d H:i:s' ) ), strtotime( $post->post_date_gmt ), 'The dates should be equal', 2 ); } + + /** + * Test ensuring that wp_update_post() does not unintentionally modify post tags + * if the post has several tags with the same name but different slugs. + * + * Tags should only be modified if 'tags_input' parameter was explicitly provided, + * and is different from the existing tags. + * + * @ticket 45121 + */ + public function test_update_post_should_only_modify_post_tags_if_different_tags_input_was_provided() { + $tag_1 = wp_insert_term( 'wp_update_post_tag', 'post_tag', array( 'slug' => 'wp_update_post_tag_1' ) ); + $tag_2 = wp_insert_term( 'wp_update_post_tag', 'post_tag', array( 'slug' => 'wp_update_post_tag_2' ) ); + $tag_3 = wp_insert_term( 'wp_update_post_tag', 'post_tag', array( 'slug' => 'wp_update_post_tag_3' ) ); + + $post_id = self::factory()->post->create( + array( + 'tags_input' => array( $tag_1['term_id'], $tag_2['term_id'] ), + ) + ); + + $post = get_post( $post_id ); + + $tags = wp_get_post_tags( $post->ID, array( 'fields' => 'ids' ) ); + $this->assertEqualSets( array( $tag_1['term_id'], $tag_2['term_id'] ), $tags ); + + wp_update_post( $post ); + + $tags = wp_get_post_tags( $post->ID, array( 'fields' => 'ids' ) ); + $this->assertEqualSets( array( $tag_1['term_id'], $tag_2['term_id'] ), $tags ); + + wp_update_post( + array( + 'ID' => $post->ID, + 'tags_input' => array( $tag_2['term_id'], $tag_3['term_id'] ), + ) + ); + + $tags = wp_get_post_tags( $post->ID, array( 'fields' => 'ids' ) ); + $this->assertEqualSets( array( $tag_2['term_id'], $tag_3['term_id'] ), $tags ); + } }