Make WordPress Core

Opened 6 years ago

Last modified 6 years ago

#44805 assigned defect (bug)

Resurrecting post from trash reverts its slug

Reported by: ajmccluskey's profile ajmccluskey Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.9.7
Component: Posts, Post Types Keywords: 2nd-opinion reporter-feedback
Focuses: Cc:

Description

Steps to reproduce

Using the REST API:

  • Create a post
  • Delete the post (not forced)
  • Update the post's slug
  • Update the post's status to publish

Create

POST wp-json/wp/v2/posts

{
  "status": "publish",
  "slug": "a",
  "title": "a"
}

Delete

DELETE wp-json/wp/v2/posts/<id>

Update slug

POST wp-json/wp/v2/posts/<id>

{
  "slug": "foo"
}

Update status

POST wp-json/wp/v2/posts/<id>

{
  "status": "publish"
}

Expected

Post should be published with a slug of foo (the updated value)

Actual

Post is published with a slug of a (the old value)

Change History (4)

#1 follow-up: @JPry
6 years ago

  • Component changed from General to Posts, Post Types
  • Focuses rest-api removed
  • Keywords 2nd-opinion added

This isn't unique to the REST API. You can observe the same behavior by using wp_update_post() directly with PHP.

<?php
$id = wp_insert_post( [
    'post_status' => 'publish',
    'post_name'   => 'a',
    'post_title'  => 'a',
] );

wp_update_post( [
    'ID'          => $id,
    'post_status' => 'trash',
] );

wp_update_post( [
    'ID'        => $id,
    'post_name' => 'foo',
] );

wp_update_post( [
    'ID'          => $id,
    'post_status' => 'publish',
] );

$post = get_post( $id );

// $post->post_name will be 'a' instead of 'foo'.

This is caused by this block within wp_insert_post():

<?php
        /*
         * If the post is being untrashed and it has a desired slug stored in post meta,
         * reassign it.
         */
        if ( 'trash' === $previous_status && 'trash' !== $post_status ) {
                $desired_post_slug = get_post_meta( $post_ID, '_wp_desired_post_slug', true );
                if ( $desired_post_slug ) {
                        delete_post_meta( $post_ID, '_wp_desired_post_slug' );
                        $post_name = $desired_post_slug;
                }
        }

When the slug is changed for a trashed post, the _wp_desired_post_slug meta is never updated to match the new slug. This is a bit of an edge case, because once a post is trashed, the slug is modified, as seen just a few lines below the previous snippet:

<?php
        // When trashing an existing post, change its slug to allow non-trashed posts to use it.
        if ( 'trash' === $post_status && 'trash' !== $previous_status && 'new' !== $previous_status ) {
                $post_name = wp_add_trashed_suffix_to_post_name_for_post( $post_ID );
        }

In the case of this example, it will be set to a__trashed. The expectation is that a trashed post's slug is not canonical, and the slug is able to be used by other posts and is not blocked from reuse by a trashed post.

With that in mind, I'm not convinced that this is actually a bug. But I think it's still worth some discussion to determine what should be the correct behavior for this edge case.

Out of curiosity, why would you want to change the slug of a trashed post in the first place?

#2 in reply to: ↑ 1 @ajmccluskey
6 years ago

Thanks for the quick reply @JPry.

As a user who is not familiar with WordPress' codebase, this seems like quite strange behaviour to me. I would generally expect that whenever I change content, especially anything user facing, the change sticks.

I agree that editing a trashed post might happen less frequently than other scenarios, however that doesn't alter my expectations. Given the size of WordPress' user base, I doubt that I'm the first or last person to do this either.

This behaviour is also seen when you update the post to published and change its slug in the same update. This might be a more likely scenario, and I would argue that a user's expectations in taking this action are very likely "publish this post with the changes that I'm making".

Last edited 6 years ago by ajmccluskey (previous) (diff)

#3 @johnbillion
6 years ago

  • Keywords reporter-feedback added

Thanks for the report @ajmccluskey! What's the use case for editing the slug of a post while it's in the trash?

#4 @ajmccluskey
6 years ago

Hi @johnbillion ,

I don't have a use case. I was testing out the API and, in lieu of a spec, I went with my expectations of what the API should do. In some cases I've adjusted my expectations, but in this case I can't think of a good reason for user changes to not be persisted, so I filed it as a bug.

I agree that this might be rare or unlikely, and therefore a low priority, but it's still part of the public API so I think it should be addressed.

Note: See TracTickets for help on using tickets.