diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 3d5b2f5c1a6ac..db8f97f8c4479 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -5208,9 +5208,11 @@ function wp_update_post( $postarr = array(), $wp_error = false, $fire_after_hook $post_cats = $post['post_category']; } - // Drafts shouldn't be assigned a date unless explicitly done so by the user. + // Drafts and Pending Review posts shouldn't be assigned a date unless explicitly done so by the user. + // Additionally, if the post_status is being updated to 'future', do not clear the date. if ( isset( $post['post_status'] ) && in_array( $post['post_status'], array( 'draft', 'pending', 'auto-draft' ), true ) + && ( ! isset( $postarr['post_status'] ) || 'future' !== $postarr['post_status'] ) && empty( $postarr['edit_date'] ) && ( '0000-00-00 00:00:00' === $post['post_date_gmt'] ) ) { $clear_date = true; diff --git a/tests/phpunit/tests/post/wpInsertPost.php b/tests/phpunit/tests/post/wpInsertPost.php index 701a48bdea311..4031bc99e16e3 100644 --- a/tests/phpunit/tests/post/wpInsertPost.php +++ b/tests/phpunit/tests/post/wpInsertPost.php @@ -529,7 +529,6 @@ public function test_wp_insert_post_should_invalidate_post_cache_before_generati /** * @ticket 55877 - * @covers ::wp_insert_post */ public function test_wp_insert_post_should_not_trigger_warning_for_pending_posts_with_unknown_cpt() { $post_id = wp_insert_post( @@ -636,19 +635,16 @@ public function test_get_post_ancestors_within_loop() { /** * @ticket 23474 - * @covers ::wp_update_post */ - public function test_update_invalid_post_id() { + public function test_insert_invalid_post_id() { $post_id = self::factory()->post->create(); $post = get_post( $post_id, ARRAY_A ); $post['ID'] = 123456789; $this->assertSame( 0, wp_insert_post( $post ) ); - $this->assertSame( 0, wp_update_post( $post ) ); $this->assertInstanceOf( 'WP_Error', wp_insert_post( $post, true ) ); - $this->assertInstanceOf( 'WP_Error', wp_update_post( $post, true ) ); } /** @@ -960,48 +956,6 @@ public function test_insert_post_should_respect_date_floating_post_status_arg_no ); } - /** - * 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 - * @covers ::wp_update_post - */ - 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->assertSameSets( 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->assertSameSets( 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->assertSameSets( array( $tag_2['term_id'], $tag_3['term_id'] ), $tags ); - } - /** * @ticket 52187 */ diff --git a/tests/phpunit/tests/post/wpPublishPost.php b/tests/phpunit/tests/post/wpPublishPost.php index 25fa87a71c91d..0ff0c2766bca5 100644 --- a/tests/phpunit/tests/post/wpPublishPost.php +++ b/tests/phpunit/tests/post/wpPublishPost.php @@ -79,37 +79,6 @@ public function test_wp_insert_post_should_default_to_publish_if_post_date_is_wi $this->assertSame( $future_date, $post->post_date ); } - /** - * @ticket 22944 - * @covers ::wp_update_post - */ - public function test_wp_update_post_with_content_filtering() { - kses_remove_filters(); - - $post_id = wp_insert_post( - array( - 'post_title' => '', - ) - ); - $post = get_post( $post_id ); - $this->assertSame( '', $post->post_title ); - $this->assertSame( 'draft', $post->post_status ); - - kses_init_filters(); - - wp_update_post( - array( - 'ID' => $post->ID, - 'post_status' => 'publish', - ) - ); - - kses_remove_filters(); - - $post = get_post( $post->ID ); - $this->assertSame( 'Test', $post->post_title ); - } - /** * @ticket 22944 */ diff --git a/tests/phpunit/tests/post/wpUpdatePost.php b/tests/phpunit/tests/post/wpUpdatePost.php new file mode 100644 index 0000000000000..5d8592d8ee820 --- /dev/null +++ b/tests/phpunit/tests/post/wpUpdatePost.php @@ -0,0 +1,260 @@ + null, + 'editor' => null, + 'contributor' => null, + ); + + /** + * Set up before class. + * + * @param WP_UnitTest_Factory $factory The Unit Test Factory. + */ + public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { + self::$user_ids = array( + 'administrator' => $factory->user->create( + array( + 'role' => 'administrator', + ) + ), + 'editor' => $factory->user->create( + array( + 'role' => 'editor', + ) + ), + 'contributor' => $factory->user->create( + array( + 'role' => 'contributor', + ) + ), + ); + + $role = get_role( 'administrator' ); + $role->add_cap( 'publish_mapped_meta_caps' ); + $role->add_cap( 'publish_unmapped_meta_caps' ); + } + + /** + * Tear down after class. + */ + public static function wpTearDownAfterClass() { + $role = get_role( 'administrator' ); + $role->remove_cap( 'publish_mapped_meta_caps' ); + $role->remove_cap( 'publish_unmapped_meta_caps' ); + } + + /** + * Set up. + */ + public function set_up() { + parent::set_up(); + + register_post_type( + 'mapped_meta_caps', + array( + 'capability_type' => array( 'mapped_meta_cap', 'mapped_meta_caps' ), + 'map_meta_cap' => true, + ) + ); + + register_post_type( + 'unmapped_meta_caps', + array( + 'capability_type' => array( 'unmapped_meta_cap', 'unmapped_meta_caps' ), + 'map_meta_cap' => false, + ) + ); + + register_post_type( + 'no_admin_caps', + array( + 'capability_type' => array( 'no_admin_cap', 'no_admin_caps' ), + 'map_meta_cap' => false, + ) + ); + } + + /** + * Test updating a post with an invalid ID. + * + * @ticket 23474 + */ + public function test_update_invalid_post_id() { + $post_id = self::factory()->post->create(); + $post = get_post( $post_id, ARRAY_A ); + + $post['ID'] = 123456789; + + $this->assertSame( 0, wp_update_post( $post ) ); + + $this->assertInstanceOf( 'WP_Error', wp_update_post( $post, true ) ); + } + + /** + * 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->assertSameSets( 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->assertSameSets( 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->assertSameSets( array( $tag_2['term_id'], $tag_3['term_id'] ), $tags ); + } + + /** + * Test the wp_update_post() filters post content when 'post_status' is 'draft'. + * + * @ticket 22944 + */ + public function test_wp_update_post_with_content_filtering() { + kses_remove_filters(); + + $post_id = wp_insert_post( + array( + 'post_title' => '', + ) + ); + $post = get_post( $post_id ); + $this->assertSame( '', $post->post_title ); + $this->assertSame( 'draft', $post->post_status ); + + kses_init_filters(); + + wp_update_post( + array( + 'ID' => $post->ID, + 'post_status' => 'publish', + ) + ); + + kses_remove_filters(); + + $post = get_post( $post->ID ); + $this->assertSame( 'Test', $post->post_title ); + } + + /** + * Test updating a post and preserving post_date when changing to future status. + * + * @ticket 62468 + * + * @dataProvider data_update_post_preserves_date_for_future_posts + * + * @param string $initial_status Initial post status. + * @param string $time_offset Time offset. + * @param string $expected_status Expected post status. + */ + public function test_update_post_preserves_date_for_future_posts( $initial_status, $time_offset, $expected_status ) { + + $post_id = self::factory()->post->create( + array( + 'post_status' => $initial_status, + ) + ); + + $future_date = gmdate( 'Y-m-d H:i:s', strtotime( $time_offset ) ); + $update_data = array( + 'ID' => $post_id, + 'post_status' => 'future', + 'post_date' => $future_date, + ); + + wp_update_post( $update_data ); + $updated_post = get_post( $post_id ); + + $this->assertSame( $future_date, $updated_post->post_date ); + $this->assertSame( $expected_status, $updated_post->post_status ); + } + + /** + * Data provider for test_update_post_preserves_date_for_future_posts. + * + * @return array[] Test parameters. + */ + public function data_update_post_preserves_date_for_future_posts() { + return array( + 'pending to future with 1 day more' => array( + 'initial_status' => 'pending', + 'time_offset' => '+1 day', + 'expected_status' => 'future', + ), + 'draft to future with 1 day more' => array( + 'initial_status' => 'draft', + 'time_offset' => '+1 day', + 'expected_status' => 'future', + ), + 'publish to future with 1 day more' => array( + 'initial_status' => 'publish', + 'time_offset' => '+1 day', + 'expected_status' => 'publish', + ), + 'draft to future with 1 day less' => array( + 'initial_status' => 'draft', + 'time_offset' => '-1 day', + 'expected_status' => 'publish', + ), + 'pending to future with 1 day less' => array( + 'initial_status' => 'pending', + 'time_offset' => '-1 day', + 'expected_status' => 'publish', + ), + 'publish to future with 1 day less' => array( + 'initial_status' => 'publish', + 'time_offset' => '-1 day', + 'expected_status' => 'publish', + ), + ); + } +}