Make WordPress Core

Opened 6 years ago

Last modified 4 weeks ago

#48954 new enhancement

"Sticky" post state shows even for non-Post post-types

Reported by: johnjamesjacoby's profile johnjamesjacoby Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Posts, Post Types Keywords: good-first-bug has-test-info has-patch has-unit-tests
Focuses: administration Cc:

Description

Reported in the support forums: https://wordpress.org/support/topic/sticky-tag-remains/

When users of my Post Type Switcher plugin switch a Post into a Page, that page still shows as "Sticky" in the Pages list-table UI, even though Pages do not support the "sticky" functionality.

Attachments (1)

Screen Shot 2019-12-12 at 3.58.40 PM.png (101.0 KB) - added by johnjamesjacoby 6 years ago.
Sticky Page in Pages List Table

Download all attachments as: .zip

Change History (9)

@johnjamesjacoby
6 years ago

Sticky Page in Pages List Table

#1 @johnjamesjacoby
6 years ago

This is immediately because the is_sticky() function does not discriminate between types of posts, which I actually think isn't really the ultimate problem.

WordPress appears to check for post-type-stickiness in 3 different ways, if at all:

  • get_inline_data() uses if ( ! $post_type_object->hierarchical ) {
  • post_submit_meta_box() uses elseif ( $post_type == 'post' && is_sticky( $post->ID ) ) and <?php if ( $post_type == 'post' ) : ?>
  • get_post_states() uses if ( is_sticky( $post->ID ) ) {
  • XML-RPC uses ( $entry['post_type'] === 'post' && is_sticky( $entry['ID'] ) )

Looking at this problem architecturally, I believe stickiness should be something that is part of the Post Type Support API, announced via register_post_type() and checked via post_type_supports().

Using the above approach, we can normalize these checks similar to Post Formats, and we can be confident that the Admin Area UI will never leak this information to the user, even if it happens to exist in meta data (or in options in this specific case).

My suggestion could technically be perceived as a breaking change, as there is some possibility that someone is making non-Posts sticky, and relying on this quirk to display the State. My counter-argument against this, is that get_post_states() is the only place this quirk exists, and get_inline_data() is really doing the totally incorrect check no matter what.

Thoughts?

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

#2 @johnjamesjacoby
6 years ago

Note that no other post type other than Posts currently shows any of the "Stick to the top of the blog" UI in the Public meta-box or Status & Visibility section of Gutenberg.

So even once a non-Post type post gets added as a Sticky, there is no user-facing way to manage that stickiness within WordPress Admin. This makes sense in a way, because technically the data does not match the expected behavior, but again... I would argue that the availability of the UI depends on either the post-type supporting it or it already being a sticky, not and. That way it can be properly unstuck if desired, without breaking anything.

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


2 months ago

#4 @SirLouen
2 months ago

  • Keywords needs-patch good-first-bug has-test-info added
  • Milestone changed from Awaiting Review to Future Release
  • Type changed from defect (bug) to enhancement

Reproduction Report

Description

✅ This report validates that the issue can be reproduced.

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.29
  • Server: nginx/1.29.1
  • Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 140.0.0.0
  • OS: Windows 10/11
  • Theme: Twenty Twenty-Five 1.3
  • MU Plugins: None activated
  • Plugins:
    • Test Reports 1.2.0

Test Instructions

  1. Install the plugin proposed by OP to make easy the switch from Post to Page without having to deal with code or DB
  2. Create a Post and mark it Sticky
  3. Convert the Sticky Post to Page
  4. Check in the Page listing
  5. 🐞 The converted page appears there with the unsupported Sticky status

Actual Results

  1. ✅ Error condition occurs (reproduced).

Additional Notes

Looking at this problem architecturally, I believe stickiness should be something that is part of the Post Type Support API, announced via register_post_type() and checked via post_type_supports().

Looks like a good idea to be implemented. Time to move forward this ticket.

#5 @igorradovanov
5 weeks ago

Hey @SirLouen,

I'd like to publish a patch for this issue, as I've been testing this bug for quite a while.

Here's what I propose:

  • Add 'sticky' to the Post Type Support API (similar to how we handle comments and thumbnails).
  • Update is_sticky() to check post_type_supports().
  • Replace the 4 hardcoded checks scattered across core (get_inline_data, post_submit_meta_box, get_post_states, XML-RPC) with a centralized support check. Did I miss any other places that might need this change?
  • Add cleanup hooks (save_post and transition_post_status) to automatically remove the sticky status when the post type changes or when saving a post whose type doesn't support sticky.
  • By default, only the 'post' type supports sticky (for backward compatibility).

This aligns with the architectural direction mentioned by @johnjamesjacoby and helps prevent data integrity issues. Custom post types could opt in if needed.

Sound good? Any concerns before I start on the patch?

#6 @johnjamesjacoby
5 weeks ago

Sound good? Any concerns before I start on the patch?

No concerns before patching this.

Suggest a post for the developer blog to document changes there whenever they are committed.

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


4 weeks ago
#7

  • Keywords has-patch has-unit-tests added; needs-patch removed

Normalizes sticky post handling across WordPress by making stickiness a declared post type feature instead of hardcoded checks.

Core changes:

  • Updated is_sticky(), stick_post(), unstick_post() to check post_type_supports()
  • Added sticky support to 'post' type by default via add_post_type_support()
  • Normalized UI checks in get_inline_data(), post_submit_meta_box(), XML-RPC

UI fixes:

  • get_inline_data(): Changed hierarchical check to post_type_supports()
  • post_submit_meta_box(): Replaced hardcoded 'post' checks with post_type_supports()
  • XML-RPC: Updated post type checks to use post_type_supports()

Not discussed in Trac, but covered:

  • Developers can add sticky support to custom post types via 'supports' => ['sticky']
  • Prevents UI leakage of sticky status for unsupported post types
  • Maintains backward compatibility for existing 'post' behavior
  • Eliminates inconsistent sticky checks throughout WordPress core

Fixes #48954

#8 @igorradovanov
4 weeks ago

Hello @SirLouen @johnjamesjacoby
I've prepared a draft developer blog post to document these changes. Happy to share it when the patch is ready to be committed!

Note: See TracTickets for help on using tickets.