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',
+ ),
+ );
+ }
+}