Make WordPress Core

Opened 14 months ago

Last modified 14 months ago

#58813 new defect (bug)

Editing Slug to an Existing Slug causes wrong content to display

Reported by: ipstenu's profile Ipstenu Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Editor Keywords: has-patch
Focuses: Cc:

Description (last modified by SergeyBiryukov)

NOTE This only works if you have the Classic Editor plugin active.

I made a ticket there - https://github.com/WordPress/classic-editor/issues/201 - but they said it's a core bug.

I am aware this is a weird one.

The setup is as follows:

  1. Make a clean website
  2. Make a couple posts (content does not matter)
  3. Install and Activate Classic Editor
  4. Make a new post and save as draft
  5. Copy the permalink from an existing post and paste it into the new post as the permalink, save as DRAFT (do not publish)
  6. You will see the NEW post has a -2 added to the permalink (this is as expected)
  7. Open the ORIGINAL existing post with the non -2
  8. The post will display the content (title and all!) from the NEW post that is still in draft (this is NOT expected)

This does not happen with the Block Editor, it can only be reproduced in Classic Editor, however the CE side feels this is a bug in core.

I dug up that this is fixed in Gutenberg per #52422 however it still exists in classic editor.

I can confirm that this happens from WP 4.9.x through 6.0.x without Classic Editor.

As of 6.1.3, this is fixed in Block Editor, and only appears if you have the Classic Editor active.

Attachments (1)

sample_vs_slug.png (90.5 KB) - added by petitphp 14 months ago.
Screenshot demonstrating the difference between sample permalink and current post slug

Download all attachments as: .zip

Change History (6)

#1 @SergeyBiryukov
14 months ago

  • Description modified (diff)

#2 @petitphp
14 months ago

I can reproduce the issue in WordPress 6.2.2 with the classic-editor plugin, or in WordPress 4.9.18 without the classic-editor.

After a bit of digging, it seems to be caused by two things.

Sample permalink in the editor is not accurate

What's displayed in the sample permalink is what the post should end up using when published. This value is provided by the sample-permalink ajax action.

In reality, the value sent to the server when saving the draft is the original permalink post_name. It can be viewed by enabling the "Slug" box in the Screen options.

Function wp_unique_post_slug doesn't do anything for draft/pending posts

The function will always return the original post name for draft posts. So the duplicate post_name will be inserted in database while the post is not published.

Ultimately those things combined end up causing the bug you described, since the WP_Query order results by post_date DESC, the wrong post is retrieved on front.

This only happen when a user set a custom post_name for a draft post, that's what trigger the duplicate post_name to be inserted in the database.

The way they fix it in the block editor is by forcing wp_unique_post_slug to return an actual unique slug in the post rest controller (post_status is set to "publish" even for draft/pending posts).


The most straight-forward way of fixing this bug would be to change the wp_unique_post_slug to always return a unique post_name even for draft/pending posts.

@petitphp
14 months ago

Screenshot demonstrating the difference between sample permalink and current post slug

#3 @Ipstenu
14 months ago

Changing this:

function wp_unique_post_slug( $slug, $post_id, $post_status, $post_type, $post_parent ) {
	if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ), true )
		|| ( 'inherit' === $post_status && 'revision' === $post_type ) || 'user_request' === $post_type
	) {
		return $slug;
	}

to this:

function wp_unique_post_slug( $slug, $post_id, $post_status, $post_type, $post_parent ) {
	if ( in_array( $post_status, array( 'auto-draft' ), true )
		|| ( 'inherit' === $post_status && 'revision' === $post_type ) || 'user_request' === $post_type
	) {
		return $slug;
	}

works, except that it doesn't fill in the slug 'block' (the one that shows the current post slug) until you either edit the permalink or publish, which isn't a good UX.

There's also the frustrating issue where the filter doesn't exist until AFTER it checks for post status, so you can never filter on those.

This ticket was mentioned in PR #4869 on WordPress/wordpress-develop by @Ipstenu.


14 months ago
#4

  • Keywords has-patch added

Currently the wp_unique_post_slug function does not check on draft posts which can cause data from the wrong post to display if a slug is reused, as it does not properly append -2.

This change treats drafts the same as published, something that is already hackey fixed for the block editor.

It has been tested with and without classic editor active.

#5 @Ipstenu
14 months ago

Okay I made a patch that effectively does the same thing as the Block Editor, by treating drafts like they're regular posts.

I do wonder if we should look into issues with pending as well, but that feels even more niche...

ETA: Also now removes the hack for Block Editor and checked that it still behaves as expected.

Last edited 14 months ago by Ipstenu (previous) (diff)
Note: See TracTickets for help on using tickets.