Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Fix backslashes being stripped from post content when using the Copy Post (Duplicate) feature.
7 changes: 6 additions & 1 deletion projects/plugins/jetpack/modules/copy-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,12 @@ protected function update_content( $source_post, $target_post_id ) {
* @param int $target_post_id Target post ID.
*/
$data = apply_filters( 'jetpack_copy_post_data', $data, $source_post, $target_post_id );
return wp_update_post( $data );

// wp_update_post() expects slashed data when passing an array.
// Since the data comes from get_post() (which returns unslashed data),
// we need to re-slash it to prevent wp_unslash() from stripping
// backslashes and other escape sequences from the content.
return wp_update_post( wp_slash( $data ) );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
*
* @group copy-post
* @covers Jetpack_Copy_Post::copy_footnotes
* @covers Jetpack_Copy_Post::update_content
*/
#[Group( 'copy-post' )]
#[CoversMethod( Jetpack_Copy_Post::class, 'copy_footnotes' )]
#[CoversMethod( Jetpack_Copy_Post::class, 'update_content' )]
class Copy_Post_Test extends WP_UnitTestCase {
use \Automattic\Jetpack\PHPUnit\WP_UnitTestCase_Fix;

Expand Down Expand Up @@ -257,4 +259,66 @@ public function test_copy_footnotes_preserves_content() {
$this->assertIsArray( $target_footnotes );
$this->assertEquals( $footnote_content, $target_footnotes[0]['content'] );
}

/**
* Test that backslashes are preserved when copying post content.
*
* @see https://github.com/Automattic/jetpack/issues/46020
*/
public function test_update_content_preserves_backslashes() {
$copy_post = new Jetpack_Copy_Post();

$content_with_backslashes = '<!-- wp:code -->
<pre class="wp-block-code"><code>\t is a tab
\n is newline
\\ is backslash</code></pre>
<!-- /wp:code -->';

$source_post_id = self::factory()->post->create(
array(
'post_content' => $content_with_backslashes,
)
);
$source_post = get_post( $source_post_id );

$target_post_id = self::factory()->post->create();

// Call update_content which is the method under test.
$result = $copy_post->update_content( $source_post, $target_post_id );

// Assert wp_update_post succeeded.
$this->assertNotEquals( 0, $result );

// Fetch the target post and verify backslashes are preserved.
$target_post = get_post( $target_post_id );
$this->assertEquals( $content_with_backslashes, $target_post->post_content );
}

/**
* Test that update_content preserves content with special escape sequences.
*
* @see https://github.com/Automattic/jetpack/issues/46020
*/
public function test_update_content_preserves_escape_sequences() {
$copy_post = new Jetpack_Copy_Post();

// Various backslash sequences that should be preserved.
$content = '<p>\t \n \f \\ \9 \ </p>';

$source_post_id = self::factory()->post->create(
array(
'post_content' => $content,
)
);
$source_post = get_post( $source_post_id );

$target_post_id = self::factory()->post->create();

$result = $copy_post->update_content( $source_post, $target_post_id );

$this->assertNotEquals( 0, $result );

$target_post = get_post( $target_post_id );
$this->assertEquals( $content, $target_post->post_content, 'Backslash escape sequences should be preserved when copying posts.' );
}
}