Make WordPress Core

Opened 2 years ago

Closed 20 months ago

#57023 closed defect (bug) (fixed)

_update_posts_count_on_delete() is still called incorrectly

Reported by: sergeybiryukov's profile SergeyBiryukov Owned by: sergeybiryukov's profile SergeyBiryukov
Milestone: 6.2 Priority: normal
Severity: normal Version: 5.9
Component: Posts, Post Types Keywords: has-patch
Focuses: multisite Cc:

Description

Background: #27952, #53443.

Some history of the affected code:

  • [28835] introduced _update_posts_count_on_delete() hooked to delete_post.
  • [52207] moved the call to after_delete_post, which runs after the post is actually deleted from the database.

The issue is that _update_posts_count_on_delete() checks the status of the post being deleted, and then only calls update_posts_count() if the deleted post was previously published, as the query would be unnecessary otherwise. Since the post is no longer available, the function bails early and update_posts_count() is never called:

  • In [28835], the post count could be off by one because the function was called too early.
  • In [52207], the function is called in the right place, but the post status check no longer works.

Why didn't the associated unit test catch this? Because it calls wp_delete_post() without the $force_delete argument, so the post is actually trashed, not deleted, and the after_delete_post action never runs.

Coincidentally, the assertion still works because of _update_posts_count_on_transition_post_status(), which runs on transition_post_status as the post is trashed. That means the test passes, but it does not test both callbacks as it's supposed to, only one of them.

Since after_delete_post receives the post object as the second argument, the solution would be to use that object for the status check, instead of trying to retrieve the post by an ID that no longer exists.

Attachments (2)

57023.diff (2.3 KB) - added by SergeyBiryukov 2 years ago.
57023.2.diff (2.3 KB) - added by SergeyBiryukov 2 years ago.

Download all attachments as: .zip

Change History (10)

#1 @SergeyBiryukov
2 years ago

  • Owner set to SergeyBiryukov
  • Status changed from new to accepted

#2 @SergeyBiryukov
2 years ago

In 54760:

Tests: Combine duplicate update_posts_count() tests.

This combines the newer test for update_posts_count() located in its own file with the pre-existing one from tests/multisite/site.php, which was essentially testing the same thing in a similar way.

Includes:

  • Renaming the test class per the naming conventions.
  • Adjusting comments per the documentation standards.
  • Updating @covers tags for accuracy.
  • Removing unnecessary blog switching.
  • Using assertSame() to check the value type.

Follow-up to [28835], [29667], [52207].

See #57023, #56793.

#3 @SergeyBiryukov
2 years ago

  • Keywords has-patch added

57023.diff fixes the issue and corrects the test so that it actually fails before the fix and passes after.

@SergeyBiryukov
2 years ago

#4 @SergeyBiryukov
2 years ago

In 54762:

Tests: Restore blog switching in update_posts_count() test.

The previous iteration of the test passed when run in isolation but failed when running the whole test suite.

Restoring the switch_to_blog() call allows the test to pass again pending a deeper investigation.

Follow-up to [54760].

See #57023.

This ticket was mentioned in Slack in #core by mukeshpanchal27. View the logs.


20 months ago

#6 @mukesh27
20 months ago

This ticket was discussed during the recent bug scrub. It looks like it's unlikely that work will be done on this during the 6.2 cycle.

@SergeyBiryukov Is this still possible to land in 6.2, or should it be moved to Future Release for now?

This ticket was mentioned in Slack in #core by costdev. View the logs.


20 months ago

#8 @SergeyBiryukov
20 months ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 55419:

Posts, Post Types: Pass the post object to _update_posts_count_on_delete().

The function checks the status of the post being deleted, and then only calls update_posts_count() if the deleted post was previously published, as the update query would be unnecessary otherwise.

However, by the time the function runs, the post is already deleted from the database, and the post status check fails.

This commit uses the previously retrieved post object for the status check, so that the function proceeds as expected.

Includes updating the unit test to call wp_delete_post() with the $force_delete argument, so that the post is actually deleted, not trashed, and the after_delete_post action is run.

Follow-up to [28835], [52207], [54760], [54762].

Fixes #57023.

Note: See TracTickets for help on using tickets.