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 | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | Editor | Keywords: | has-patch |
Focuses: | Cc: |
Description (last modified by )
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:
- Make a clean website
- Make a couple posts (content does not matter)
- Install and Activate Classic Editor
- Make a new post and save as draft
- Copy the permalink from an existing post and paste it into the new post as the permalink, save as DRAFT (do not publish)
- You will see the NEW post has a -2 added to the permalink (this is as expected)
- Open the ORIGINAL existing post with the non -2
- 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)
Change History (6)
@
14 months ago
Screenshot demonstrating the difference between sample permalink and current post slug
#3
@
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
@
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.
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.