Make WordPress Core

Opened 8 years ago

Last modified 5 years ago

#35131 new defect (bug)

Unexpected 404: pending post hides published post with matching slug

Reported by: bobbingwide's profile bobbingwide Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.3.1
Component: Query Keywords:
Focuses: Cc:

Description

While attempting to recreate #35012 and #35031 I also noted the anomaly previously reported in #22902 where an authorized user could see all the posts displayed as if they were a single page.

Investigating this led me to determining that the existence of a new "pending" post with the same slug as an existing post prevents the user from visiting the existing post using its permalink.

Example:
post: 31766, status: pending, title: Cycle 1, slug: cycle-1 date: 2015-12-16 11:18:26
Content: You might be able to see this if you're logged in.

post: 31764, status: publish, title: Cycle 1, slug: cycle-1 date: 2015-12-16 11:17:17
Content: You should be able to see this.

Steps:

  1. Create posts as above
  2. Log out or otherwise visit the site as a visitor
  3. View the blog page or the archive
  4. Note that you see the published post, not the pending post
  5. Click on the published post's permalink
  6. You'll get a 404.

Expected result

Displays the published post.

Actual result

Displays a 404 page.

Explanation

  • The query in WP_query returns two posts: 31766:pending and 31764:publish.
  • Even though there are two posts in the result set, is_single is true.
  • The logic to "Check post status to determine if post should be displayed." kicks in and the post array is emptied.
  • This eventually leads to the 404.

My Conclusion

There are two problems leading to this one

  1. The pending post should not have been given the same slug as the published post.
  2. is_single should not have been set to true.

Proposed solution

If it's not possible to deal with the underlying cause then the logic in the "Check post status..." should be adjusted to filter out the posts that the user shouldn't have been able to see. If the resulting set contains more than one post then is_single should become false.

I noticed this on 4.4 but have reproduced it on 4.3.
I imagine the actual bug goes back a long long way.


Attachments (1)

35131.diff (3.7 KB) - added by boonebgorges 8 years ago.

Download all attachments as: .zip

Change History (4)

#1 @bobbingwide
8 years ago

Workaround

Don't create pending posts with the same slug.
e.g. Create the pending post first.

#2 @boonebgorges
8 years ago

I'm unable to reproduce the slug conflict in the manner described.

Sometimes WP creates 'pending' posts with empty post_name - I think this happens when the sample permalink is not customized. When this is the case, there's no slug conflict, since the pending post doesn't have a slug.

Sometimes WP does save a post_name with a pending post. In these cases, it's not possible to create a published post through the Add New Post interface using the same slug. The get_sample_permalink() -> wp_unique_post_slug() chain prevents it, appending the -2 suffix.

Am I doing something different from what you're doing?

I'm able to reproduce the WP_Query routing problem when I manually update the database so that there's a slug conflict. I'm not certain it's a scenario we need to design for.

That being said, 35131.diff is an attempt to adjust the post_status filter logic for the possibility that there may be more than one post return by a singular-post query, and that the "public" one might not be at the 0 index. This needs cleanup and probably lots of unit tests. @bobbingwide Can you take a look to see if this approach addresses your bug? (It does for me.)

See also #30911.

@boonebgorges
8 years ago

#3 @bobbingwide
8 years ago

Hi @boonebgorges, my database still contained the posts that exhibited the problem but it took me a long time to discover the steps to reproduce the starting point.
That's because what you see in the Permalink field in Edit post is misleading.

This appears to be the simplest method of creating the duplicate posts.

  1. Add new post with title "TRAC 35131". Publish
  2. Add another new post with title "TRAC 35131". Publish
  3. Edit the permalink of the new post, from "trac-35131-2" to "trac-35131", change status to Pending and Update.

Although the permalink of the new post appears to be "trac-35131-2" the database is still showing it as "trac-35131", the same as for the post in step 1.

Repeat steps 2 and 3 to create more duplicates.

BTW. I haven't tried the fix yet.

Last edited 8 years ago by bobbingwide (previous) (diff)
Note: See TracTickets for help on using tickets.