diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index 747bcc75e53eb..fb50754696dc8 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -1649,21 +1649,25 @@ function wp_ajax_add_meta() { // If the post is an autodraft, save the post as a draft and then attempt to save the meta. if ( 'auto-draft' === $post->post_status ) { - $post_data = array(); - $post_data['action'] = 'draft'; // Warning fix. - $post_data['post_ID'] = $post_id; - $post_data['post_type'] = $post->post_type; - $post_data['post_status'] = 'draft'; - $now = time(); - - $post_data['post_title'] = sprintf( - /* translators: 1: Post creation date, 2: Post creation time. */ - __( 'Draft created on %1$s at %2$s' ), - gmdate( __( 'F j, Y' ), $now ), - gmdate( __( 'g:i a' ), $now ) + $now = time(); + + /* + * Update the post directly instead of via edit_post(), which would + * add the meta a second time from the $_POST data and reset the + * comment and ping status of the post to 'closed'. See #66016. + */ + $post_data = array( + 'ID' => $post_id, + 'post_status' => 'draft', + 'post_title' => sprintf( + /* translators: 1: Post creation date, 2: Post creation time. */ + __( 'Draft created on %1$s at %2$s' ), + gmdate( __( 'F j, Y' ), $now ), + gmdate( __( 'g:i a' ), $now ) + ), ); - $post_id = edit_post( $post_data ); + $post_id = wp_update_post( $post_data, true ); if ( $post_id ) { if ( is_wp_error( $post_id ) ) { @@ -1676,6 +1680,8 @@ function wp_ajax_add_meta() { $response->send(); } + update_post_meta( $post_id, '_edit_last', get_current_user_id() ); + $meta_id = add_meta( $post_id ); if ( ! $meta_id ) { diff --git a/tests/phpunit/tests/ajax/wpAjaxAddMeta.php b/tests/phpunit/tests/ajax/wpAjaxAddMeta.php index dbaee104baea5..4f759c7da72a9 100644 --- a/tests/phpunit/tests/ajax/wpAjaxAddMeta.php +++ b/tests/phpunit/tests/ajax/wpAjaxAddMeta.php @@ -75,4 +75,75 @@ public function test_wp_ajax_add_meta_allows_empty_values_on_updating() { $this->assertSame( '', get_post_meta( $post, 'testkey', true ) ); } + + /** + * Adding meta to an auto-draft should only create the meta once. + * + * @ticket 66016 + */ + public function test_adding_meta_to_an_auto_draft_should_not_duplicate_the_meta() { + $post = self::factory()->post->create( + array( + 'post_status' => 'auto-draft', + ) + ); + + // Become an administrator. + $this->_setRole( 'administrator' ); + + $_POST = array( + 'post_id' => $post, + 'metakeyinput' => 'testkey', + 'metavalue' => 'testvalue', + '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ), + ); + + // Make the request. + try { + $this->_handleAjax( 'add-meta' ); + } catch ( WPAjaxDieContinueException $e ) { + unset( $e ); + } + + $this->assertSame( array( 'testvalue' ), get_post_meta( $post, 'testkey' ) ); + } + + /** + * Adding meta to an auto-draft should save the post as a draft + * without changing its comment or ping status. + * + * @ticket 66016 + */ + public function test_adding_meta_to_an_auto_draft_should_not_change_the_comment_and_ping_status() { + $post = self::factory()->post->create( + array( + 'post_status' => 'auto-draft', + 'comment_status' => 'open', + 'ping_status' => 'open', + ) + ); + + // Become an administrator. + $this->_setRole( 'administrator' ); + + $_POST = array( + 'post_id' => $post, + 'metakeyinput' => 'testkey', + 'metavalue' => 'testvalue', + '_ajax_nonce-add-meta' => wp_create_nonce( 'add-meta' ), + ); + + // Make the request. + try { + $this->_handleAjax( 'add-meta' ); + } catch ( WPAjaxDieContinueException $e ) { + unset( $e ); + } + + $post = get_post( $post ); + + $this->assertSame( 'draft', $post->post_status, 'The auto-draft should have been saved as a draft.' ); + $this->assertSame( 'open', $post->comment_status, 'The comment status of the post should not have changed.' ); + $this->assertSame( 'open', $post->ping_status, 'The ping status of the post should not have changed.' ); + } }