Ticket #7457 (closed enhancement: fixed)

Opened 5 months ago

Last modified 4 months ago

Sticky Posts

Reported by: ryan Assigned to: anonymous
Priority: normal Milestone: 2.7
Component: General Version:
Severity: normal Keywords: sticky posts blessed
Cc:

Description

By popular demand, Sticky Posts.

Suggested design:

  • Have "Stick to front page" checkbox on the edit post page
  • If checked, add the ID of the post to a sticky_posts field in the options table
  • When performing a front page query, move sticky posts to the head of the results. If all sticky posts are not present in the results, do a separate query to fetch the missing ones. Do this only if is_home().
  • Provide is_sticky($post_id) for use by themes.

Attachments

7457.diff (3.5 kB) - added by ryan on 08/03/08 06:31:35.
First draft, incomplete
7457.2.diff (5.1 kB) - added by ryan on 08/04/08 04:23:36.
Now with UI and one query to fetch the stickies

Change History

08/02/08 20:29:53 changed by ryan

Should sticky posts count toward the posts per page limit?

08/03/08 00:31:39 changed by technosailor

+1

Would suggest sticky posts should also apply on is_archive(), is_category(), is_tag() and most importantly is_search()...

08/03/08 01:14:32 changed by DD32

IMO, Yes, Sticky posts should count towards the limit - Still only want 10 per page even if theres a sticky

  • Should Stickies be shown on paged pages as well? Or mearly page 1.
  • Should sticky posts appear on the search results?

IMO, Sticky posts should only appear within their normal listings, So it should appear as sticky on front/archive/category/tag/etc pages, however if a sticky post was found in a search, it should float to the top as expected, But if its not found by the search, IMHO the sticky doesnt belong in that group of posts.

08/03/08 06:31:35 changed by ryan

  • attachment 7457.diff added.

First draft, incomplete

08/03/08 06:35:55 changed by ryan

Here's a first, crude attempt. Stickies are presented only on the home page, stickies do not count toward the per page count, there is no UI, and phpdoc is incomplete.

08/03/08 06:54:18 changed by ryan

Stickies that are not in the query results for page 1 don't count toward the per page limit. If they were counted, we'd have to adjust all subsequent pages so that posts bumped off the first page to make room for stickies aren't orphaned.

Showing stickies on pages other than home means we have to check to see if the stickies would be part of the results if the query were unpaged.

Counting stickies towards the page limit and showing stickies on pages other than home could be cans of worms. Should we bother?

08/03/08 07:25:39 changed by DD32

Counting stickies towards the page limit and showing stickies on pages other than home could be cans of worms. Should we bother?

I see what you mean..

Could the menu_order field be utilised to mark a post as a sticky? It'd also mean that the paging support should work as expected.

AFAIK, the menu_order field is not used by posts at all, Setting it to a >0 value for stickie would allow for the SQL ORDER BY to return Stickies first, followed by non-stickies (menu_order == 0), the SQL LIMIT would then continue working for paging.

The only real downside i can think of is an extra SQL Ordering, which could reduce performance, but i cant see it being any worse than an extra SQL to fetch any stickies. (Note: Theres no index on menu_order, it is however an int(11) though)

08/03/08 19:28:36 changed by ryan

We'd definitely need an index on menu_order for the query not to suck. We need an index on it anyway for the page query. We should only add menu_order to the query when there are stickies, so we might still want to store sticky posts in options. stick_post() would add it to options and set menu_order to 1. It's worth a try. Anyone want to try EXPLAINing the posts query with menu_order and different indexes (menu_order, post_date) and see how it performs?

08/04/08 04:22:35 changed by ryan

Adding menu_order to the sort is pretty slow. The query to fetch the sticky posts is a const query on a primary key. Very fast. Another alternative would be to UNION the regular post query and the sticky query. Don't know if its worth it though.

08/04/08 04:23:36 changed by ryan

  • attachment 7457.2.diff added.

Now with UI and one query to fetch the stickies

08/04/08 04:54:18 changed by ryan

Ordering by menu_order DESC, post_date DESC results in filesort. I've tried adding different keys to get rid of it but haven't hit upon a combination that works yet. Using menu_order does make things cleaner, but incurring filesort isn't worth it.

08/04/08 05:16:30 changed by ryan

With the current patch, posts on page 2 that are marked as sticky will show at the top of page 1 and again in their original places on page 2. You'll see them twice as you page through. I'm trying to decide whether that's a feature or a limitation. I'm leaning toward feature. I like seeing them in their original place in the timeline. If this is deemed a feature, it is an advantage over the menu_order method.

08/04/08 05:25:25 changed by DD32

Ordering by menu_order DESC, post_date DESC results in filesort.

Probably because ordering by post_date will result in a filesort regardless?

EXPLAIN SELECT * FROM `wp_posts` ORDER BY menu_order DESC , post_date DESC

id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra 
1	SIMPLE	wp_posts	ALL	NULL	NULL	NULL	NULL	196	Using filesort
EXPLAIN SELECT * FROM `wp_posts` ORDER BY post_date DESC

id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra 
1	SIMPLE	wp_posts	ALL	NULL	NULL	NULL	NULL	196	Using filesort

I cant find any form of index which helps the 2nd query let alone the first, I might be barking up the wrong tree though.

I'm leaning toward feature. I like seeing them in their original place in the timeline. If this is deemed a feature, it is an advantage over the menu_order method.

I guess that can be seen as a feature, It depends on what users of the functionality are using it for, They may only want the sticky to be shown as a sticky, Others would be using it to pin a post in place, yet still want it to show in the natural order of posts.

08/04/08 05:30:12 changed by ryan

SELECT SQL_CALC_FOUND_ROWS wp_trunk_posts.* FROM wp_trunk_posts WHERE 1=1 AND
 wp_trunk_posts.post_type = 'post' AND (wp_trunk_posts.post_status = 'publish') ORDER BY
 wp_trunk_posts.post_date DESC LIMIT 0, 10

I get "Using where" with that. Adding menu_order to the mix brings on filesort.

08/04/08 05:35:01 changed by DD32

I get "Using where" with that. Adding menu_order to the mix brings on filesort.

Ah, I was getting filesort from { AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ; So yes, You are right.

08/04/08 05:37:18 changed by ryan

Yeah, you get that if you are logged in. Would be nice to get rid of that, but at least regular users aren't hit with it.

08/04/08 05:43:29 changed by DD32

Adding menu_order to the type_status_date key and ordering it the same as the query removes the need for a filesort:

EXPLAIN SELECT SQL_CALC_FOUND_ROWS wp_posts . * 
FROM wp_posts
WHERE 1 =1
AND wp_posts.post_type = 'post'
AND (
wp_posts.post_status = 'publish'
)
ORDER BY wp_posts.menu_order DESC , wp_posts.post_date DESC 
LIMIT 0 , 10

id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra 
1	SIMPLE	wp_posts	ref	type_status_date_order	type_status_date_order	124	const,const	49	Using where

Key:

ALTER TABLE `wp_posts` DROP INDEX `type_status_date` ,
ADD INDEX `type_status_date_order` ( `post_type` , `post_status` , `menu_order` , `post_date` , `ID` )

It appears that unless the order by keys are in the order index in the same order that they're used, MySQL cannot rely on the key for the sort.

08/04/08 16:40:26 changed by ryan

Changing post_status_date makes the non-menu_order query use filesort though. I think we'd need to keep type_status_date and add type_status_order_date.

08/05/08 05:48:21 changed by ryan

(In [8546]) Sticky Posts, firct cut. see #7457

08/05/08 05:49:42 changed by ryan

I committed what I had for folks to play with. I'll tidy up and attach my menu_order patch for comparison. Each approach has its merits. It's a toss up.

08/06/08 20:29:42 changed by markjaquith

At the least, this should require publish_post capabilities. You don't want contributors checking that box and then having their post be sticky when it is eventually published. There's a decent argument to be made that this should require the edit_others_posts capability, since this is more of an editorial decision.

08/06/08 21:01:06 changed by ryan

The checkbox is only shown if publish_posts, but we might need some checks on the POST side.

08/06/08 21:01:46 changed by ryan

edit_others_post sounds good, or maybe a new cap entirely.

08/06/08 21:11:54 changed by markjaquith

Adding new capabilities is problematic. We essentially have to marry the new capability to an old capability on upgrade, and it's not built for cap2role and cap2person lookup. I think promotion of a post to "sticky" status is similar enough to the scope of responsibility that comes with being able to edit other people's posts.

08/06/08 21:23:35 changed by markjaquith

(In [8576]) Give separate paragraphs to the private/sticky checkboxen (heh) and give them distinct IDs for plugin CSS-hiding purposes. see #7457

08/06/08 21:31:40 changed by markjaquith

(In [8577]) Use the edit_others_posts capability for controlling sticky checkbox display and usage. see #7457

08/09/08 01:24:42 changed by jacobsantos

  • type changed from defect to enhancement.

08/13/08 18:21:53 changed by ryan

(In [8637]) Add sticky_class() template tag. see #7457

08/13/08 19:09:09 changed by ryan

(In [8638]) Add post_class() template function for emitting standard classes for post div. see #7457

08/13/08 19:10:44 changed by ryan

(In [8639]) phpdoc fix up for post_class(). see #7457

08/13/08 21:58:06 changed by ryan

(In [8641]) Add more classes to post_class(). see #7457

08/13/08 22:00:07 changed by ryan

(In [8642]) Initialize classes array. see #7457

08/13/08 23:26:14 changed by ryan

(In [8643]) get_post_class() from mdawaffe. see #7457

09/01/08 17:01:47 changed by ryan

  • status changed from new to closed.
  • resolution set to fixed.

(In [8795]) Suppress query filters when called from get_posts(). fixes #7326 #7457 for 2.6