Skip to content

Conversation

Copy link

Copilot AI commented Dec 1, 2025

Fixes #46020

Proposed changes:

Backslash characters (\) were being stripped from post content when duplicating posts. For example, \t is a tab became t is a tab.

Root cause: wp_update_post() internally calls wp_unslash(), expecting slashed data (like from $_POST). When passing unslashed database data directly, backslashes get stripped.

Fix: Wrap data with wp_slash() before passing to wp_update_post(), matching the pattern in WordPress Core's wp_restore_post_revision() (revision.php:485).

Changes:

  • copy-post.php: Add wp_slash() in update_content()
// Before
return wp_update_post( $data );

// After  
return wp_update_post( wp_slash( $data ) );

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

Does this pull request change what data or activity we track or use?

No.

Testing instructions:

  • Create a post with a Code block containing \t is a tab
  • Save the post
  • Click "Duplicate" from post actions
  • Verify the duplicated post retains \t is a tab (not t is a tab)
Original prompt

This section details on the original issue you should resolve

<issue_title>Copy post strips "" characters from post content</issue_title>
<issue_description>### Impacted plugin

Jetpack

Quick summary

The "copy post" or "duplicate post" functionality may incorrectly strip the \ character from post content.

This affected character is U+005C Reverse Solidus character or "backslash."

Steps to reproduce

  1. Create a post with content like this:

    <!-- wp:code -->
    <pre class="wp-block-code"><code>\t is a tab</code></pre>
    <!-- /wp:code -->

    That is a Code block with the text \t is a tab.

  2. Save the post.

  3. From the post edit view, click "Duplicate" on the post.

  4. A post is created where the text is now t is a tab:

    <!-- wp:code -->
    <pre class="wp-block-code"><code>t is a tab</code></pre>
    <!-- /wp:code -->
 <!-- wp:code -->
-<pre class="wp-block-code"><code>\t is a tab</code></pre>
+<pre class="wp-block-code"><code>t is a tab</code></pre>
 <!-- /wp:code -->

This seems to happen regularly with the \ character:

  • \t -> t
  • \n -> n
  • \f -> f
  • \\ -> \
  • \9 -> 9
  • \ -> (space)

[!NOTE]
The reproduction uses a Code block because it's easy to see the characters, but this seems to happen on any content. Text in a Paragraph block will also be affected.

Site owner impact

Fewer than 20% of the total website/platform users

Severity

Minor

What other impact(s) does this issue have?

No response

If a workaround is available, please outline it here.

No response

Platform (Simple and/or Atomic)

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 1, 2025 18:09
- Add wp_slash() wrapper in copy-post.php update_content() to preserve
  backslash characters when duplicating posts
- Add wp_slash() wrapper in markdown module's wp_restore_post_revision()
  and fix_latest_revision_on_restore() to preserve backslash characters
  when restoring revisions
- Add unit tests for copy-post backslash preservation
- Add changelog entry

Co-authored-by: sirreal <[email protected]>
Copilot AI changed the title [WIP] Fix copy post stripping backslash characters Fix backslash character stripping in Copy Post and Markdown modules Dec 1, 2025
Copilot AI requested a review from sirreal December 1, 2025 18:15
Copilot finished work on behalf of sirreal December 1, 2025 18:15
@sirreal
Copy link
Member

sirreal commented Dec 1, 2025

@copilot You should look at this history: #1703

Copy link
Author

Copilot AI commented Dec 1, 2025

@copilot You should look at this history: #1703

Thanks for sharing that context. I reviewed the history and see that PR #1703's fix was reverted because it modified the transform() and swap_for_editing() methods - core markdown transformation logic.

My changes are different in scope - I'm only adding wp_slash() wrappers in wp_restore_post_revision() and fix_latest_revision_on_restore() before calling wp_update_post()/wp_insert_post(). This follows the same pattern used in WordPress Core's wp_restore_post_revision() (revision.php:485).

The copy-post.php change is straightforward and safe. For the markdown module changes, the context is narrower - we're just ensuring DB data is properly slashed before passing to these WordPress functions, not modifying the transformation pipeline that caused issues in the old PR.

That said, given the module's complexity, if you'd prefer I revert the markdown changes and keep only the copy-post fix, let me know.

Copilot finished work on behalf of sirreal December 1, 2025 18:22
@sirreal
Copy link
Member

sirreal commented Dec 1, 2025

That said, given the module's complexity, if you'd prefer I revert the markdown changes and keep only the copy-post fix, let me know.

@copilot Since this appears to be a separate issue, you should create a separate PR for that and remove the changes from this PR.

Keep only the copy-post fix. The markdown module changes should
be addressed in a separate PR given the module's complexity and
historical issues with slash handling.

Co-authored-by: sirreal <[email protected]>
Copy link
Author

Copilot AI commented Dec 1, 2025

That said, given the module's complexity, if you'd prefer I revert the markdown changes and keep only the copy-post fix, let me know.

@copilot Since this appears to be a separate issue, you shoul...

Removed the markdown module changes in a803166. This PR now only contains the copy-post fix.

Copilot AI changed the title Fix backslash character stripping in Copy Post and Markdown modules Fix backslash character stripping in Copy Post module Dec 1, 2025
Copilot finished work on behalf of sirreal December 1, 2025 18:27
Comment on lines 2 to 20
/**
* Class Copy_Post_Test for unit testing the Copy Post module.
*
* @package automattic/jetpack
*/

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;

require_once JETPACK__PLUGIN_DIR . 'modules/copy-post.php';

/**
* @group copy-post
* @covers Jetpack_Copy_Post
*/
#[Group( 'copy-post' )]
#[CoversClass( Jetpack_Copy_Post::class )]
class Copy_Post_Test extends WP_UnitTestCase {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Is this consistent with how other unit tests are authored in this repository?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I reviewed existing tests like Jetpack_Sitemap_Finder_Test.php and GFM_Markdown_Test.php and simplified the test to follow the same patterns. Removed the redundant @group/#[Group] annotations and updated docblocks to match (8fd9c8b).

- Remove redundant @group and #[Group] annotations
- Update docblocks to match patterns from other test files
- Keep core test functionality unchanged

Co-authored-by: sirreal <[email protected]>
Copilot AI requested a review from sirreal December 1, 2025 18:34
Copilot finished work on behalf of sirreal December 1, 2025 18:34
Comment on lines 16 to 18
* @covers Jetpack_Copy_Post
*/
#[CoversClass( Jetpack_Copy_Post::class )]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of duplicated annotations (PHPdoc and PHP annotations) in this test file.

Is that standard practice for this repository?

Review them carefully @copilot. Let's adhere to best practices for this project.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the patterns and simplified the test in 83516a2. Removed the redundant @covers/#[CoversClass] annotations, following the simpler pattern used in Jetpack_Google_Font_Face_Test.php. The @dataProvider/#[DataProvider] duplication is kept as that's standard for this repo to support both older and newer PHPUnit versions.

Follow simpler pattern used in Jetpack_Google_Font_Face_Test.php:
- Remove @Covers and #[CoversClass] annotations
- Keep @dataProvider/#[DataProvider] which is the standard pattern for this repo

Co-authored-by: sirreal <[email protected]>
Copilot finished work on behalf of sirreal December 1, 2025 18:49
Copilot AI requested a review from sirreal December 1, 2025 18:49
@sirreal sirreal removed their request for review December 2, 2025 13:02
@sirreal sirreal removed their assignment Dec 2, 2025
@sirreal sirreal added [Type] Bug When a feature is broken and / or not performing as intended [Status] Needs Review This PR is ready for review. [Feature] Copy a Post Reviewer Can Merge PR author indicates the reviewer is free to merge/deploy if they want to own the change. labels Dec 2, 2025
@github-actions github-actions bot added [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Status] In Progress [Tests] Includes Tests labels Dec 2, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 2, 2025

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add a "[Type]" label (Bug, Enhancement, Janitorial, Task).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Copy a Post [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ Reviewer Can Merge PR author indicates the reviewer is free to merge/deploy if they want to own the change. [Status] In Progress [Status] Needs Review This PR is ready for review. [Tests] Includes Tests [Type] Bug When a feature is broken and / or not performing as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy post strips "\" characters from post content

2 participants