From 6abe575a2a8abeefebe5a0c8edabbe6527545f5b Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 11 Oct 2017 05:41:14 +0000 Subject: [PATCH] Customize: Introduce `WP_Customize_Manager::trash_changeset_post()` to reduce duplication and ensure proper changeset trashing logic. Trashing a changeset via `wp_trash_post()` does not have the desired result since it mutates `post_content` (via Kses) and the `post_name` (even though it is a UUID). Props dlh. See #39896, #42030. Fixes #42175. git-svn-id: https://develop.svn.wordpress.org/trunk@41824 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-customize-manager.php | 75 ++++++++++++++++++- src/wp-includes/theme.php | 42 +---------- tests/phpunit/tests/customize/manager.php | 29 +++++++ 3 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php index 3165b77066..0cc6b2a510 100644 --- a/src/wp-includes/class-wp-customize-manager.php +++ b/src/wp-includes/class-wp-customize-manager.php @@ -2830,6 +2830,79 @@ final class WP_Customize_Manager { return $response; } + /** + * Trash or delete a changeset post. + * + * The following re-formulates the logic from `wp_trash_post()` as done in + * `wp_publish_post()`. The reason for bypassing `wp_trash_post()` is that it + * will mutate the the `post_content` and the `post_name` when they should be + * untouched. + * + * @since 4.9.0 + * @global wpdb $wpdb WordPress database abstraction object. + * @see wp_trash_post() + * + * @param int|WP_Post $post The changeset post. + * @return mixed A WP_Post object for the trashed post or an empty value on failure. + */ + public function trash_changeset_post( $post ) { + global $wpdb; + + $post = get_post( $post ); + + if ( ! ( $post instanceof WP_Post ) ) { + return $post; + } + $post_id = $post->ID; + + if ( ! EMPTY_TRASH_DAYS ) { + return wp_delete_post( $post_id, true ); + } + + if ( 'trash' === get_post_status( $post ) ) { + return false; + } + + /** This filter is documented in wp-includes/post.php */ + $check = apply_filters( 'pre_trash_post', null, $post ); + if ( null !== $check ) { + return $check; + } + + /** This action is documented in wp-includes/post.php */ + do_action( 'wp_trash_post', $post_id ); + + add_post_meta( $post_id, '_wp_trash_meta_status', $post->post_status ); + add_post_meta( $post_id, '_wp_trash_meta_time', time() ); + + $old_status = $post->post_status; + $new_status = 'trash'; + $wpdb->update( $wpdb->posts, array( 'post_status' => $new_status ), array( 'ID' => $post->ID ) ); + clean_post_cache( $post->ID ); + + $post->post_status = $new_status; + wp_transition_post_status( $new_status, $old_status, $post ); + + /** This action is documented in wp-includes/post.php */ + do_action( 'edit_post', $post->ID, $post ); + + /** This action is documented in wp-includes/post.php */ + do_action( "save_post_{$post->post_type}", $post->ID, $post, true ); + + /** This action is documented in wp-includes/post.php */ + do_action( 'save_post', $post->ID, $post, true ); + + /** This action is documented in wp-includes/post.php */ + do_action( 'wp_insert_post', $post->ID, $post, true ); + + wp_trash_post_comments( $post_id ); + + /** This action is documented in wp-includes/post.php */ + do_action( 'trashed_post', $post_id ); + + return $post; + } + /** * Handle request to trash a changeset. * @@ -2876,7 +2949,7 @@ final class WP_Customize_Manager { return; } - $r = wp_trash_post( $changeset_post_id ); + $r = $this->trash_changeset_post( $changeset_post_id ); if ( ! ( $r instanceof WP_Post ) ) { wp_send_json_error( array( 'code' => 'changeset_trash_failure', diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 2ee66fbddf..ff9cf0d31e 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -2909,47 +2909,7 @@ function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_p * and thus garbage collected. */ if ( ! wp_revisions_enabled( $changeset_post ) ) { - $post = $changeset_post; - $post_id = $changeset_post->ID; - - /* - * The following re-formulates the logic from wp_trash_post() as done in - * wp_publish_post(). The reason for bypassing wp_trash_post() is that it - * will mutate the post_content and the post_name when they should be - * untouched. - */ - if ( ! EMPTY_TRASH_DAYS ) { - wp_delete_post( $post_id, true ); - } else { - /** This action is documented in wp-includes/post.php */ - do_action( 'wp_trash_post', $post_id ); - - add_post_meta( $post_id, '_wp_trash_meta_status', $post->post_status ); - add_post_meta( $post_id, '_wp_trash_meta_time', time() ); - - $old_status = $post->post_status; - $new_status = 'trash'; - $wpdb->update( $wpdb->posts, array( 'post_status' => $new_status ), array( 'ID' => $post->ID ) ); - clean_post_cache( $post->ID ); - - $post->post_status = $new_status; - wp_transition_post_status( $new_status, $old_status, $post ); - - /** This action is documented in wp-includes/post.php */ - do_action( 'edit_post', $post->ID, $post ); - - /** This action is documented in wp-includes/post.php */ - do_action( "save_post_{$post->post_type}", $post->ID, $post, true ); - - /** This action is documented in wp-includes/post.php */ - do_action( 'save_post', $post->ID, $post, true ); - - /** This action is documented in wp-includes/post.php */ - do_action( 'wp_insert_post', $post->ID, $post, true ); - - /** This action is documented in wp-includes/post.php */ - do_action( 'trashed_post', $post_id ); - } + $wp_customize->trash_changeset_post( $changeset_post->ID ); } } diff --git a/tests/phpunit/tests/customize/manager.php b/tests/phpunit/tests/customize/manager.php index 6938b7c3bb..e28f1944ee 100644 --- a/tests/phpunit/tests/customize/manager.php +++ b/tests/phpunit/tests/customize/manager.php @@ -1709,6 +1709,35 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase { $this->assertEquals( 'expected_array', $r->get_error_code() ); } + /** + * Test that trash_changeset_post() trashes a changeset post with its name and content preserved. + * + * @covers WP_Customize_Manager::trash_changeset_post + */ + public function test_trash_changeset_post_preserves_properties() { + $args = array( + 'post_type' => 'customize_changeset', + 'post_content' => wp_json_encode( array( + 'blogname' => array( + 'value' => 'Test', + ), + ) ), + 'post_name' => wp_generate_uuid4(), + 'post_status' => 'draft', + ); + + $post_id = wp_insert_post( $args ); + + $manager = $this->create_test_manager( $args['post_name'] ); + $manager->trash_changeset_post( $post_id ); + + $post = get_post( $post_id ); + + $this->assertSame( 'trash', get_post_status( $post_id ) ); + $this->assertSame( $args['post_name'], $post->post_name ); + $this->assertSame( $args['post_content'], $post->post_content ); + } + /** * Register scratchpad setting. *