WordPress.org

Make WordPress Core

Opened 10 years ago

Closed 3 years ago

#4711 closed defect (bug) (duplicate)

get_pages and get_posts do not work well with private posts

Reported by: Otto42 Owned by:
Milestone: Priority: normal
Severity: normal Version: 2.9.1
Component: Template Keywords: needs-patch featured
Focuses: Cc:

Description

The get_pages function has no way to retrieve private pages.
The get_posts function uses a post_status parameter, meaning that it can retrieve (and potentially display) private posts regardless of the user.

While get_pages() simply lacks a feature, I would argue that get_posts() is defective in that it can display things that it should not be able to display.

Both of these functions need to be updated to use the get_private_posts_cap_sql() function for building the correct post_status query segment.

Attachments (2)

4711.diff (4.1 KB) - added by Otto42 10 years ago.
Suggested patch
4711.2.diff (877 bytes) - added by chrislear 9 years ago.
A smaller diff

Download all attachments as: .zip

Change History (20)

@Otto42
10 years ago

Suggested patch

#1 @Otto42
10 years ago

  • Keywords has-patch needs-testing added

#2 follow-up: @ryan
10 years ago

get_posts and get_pages should be able to directly retrieve any post status, regardless of the current user. Plugins and the admin need to be able to get at anything. Maybe we need some more args. post_statusin => array('publish', 'private'), check_user_caps => true. Something like that.

#3 @ryan
10 years ago

  • Milestone changed from 2.3 to 2.4 (next)

#4 @westi
9 years ago

  • Milestone changed from 2.5 to 2.6
  • Type changed from defect to enhancement

marking as an enhancement

moving to 2.6 for resolving.

@chrislear
9 years ago

A smaller diff

#5 @chrislear
9 years ago

  • Version changed from 2.2.1 to 2.5

I've attached a much smaller diff that works OK for me. I ran it against a fresh Wordpress 2.5.
All it does is include private pages if it's valid to do so in get_pages.
I didn't need the extra post_status argument (or the whitespace changes) from the other diff.

#6 @chrislear
9 years ago

I should have said that I wanted this because I'm using wp_list_pages in my template header, and I want to show private pages when the user is logged on. Here's the code:

if (is_user_logged_in()) {

$exclude="&exclude=5,7"; But should include private pages

} else {

$exclude="&exclude=7";

}
wp_list_pages("title_li=&sort_column=menu_order&depth=1$exclude" );

#8 @Denis-de-Bernardy
8 years ago

  • Keywords needs-patch added; has-patch needs-testing removed
  • Milestone changed from 2.9 to Future Release
  • Priority changed from normal to low
  • Severity changed from major to minor

patch isn't good, see Ryan's comment:

http://core.trac.wordpress.org/ticket/4711#comment:2

#9 @voyagerfan5761
8 years ago

  • Cc WordPress@… added

#10 @sillybean
8 years ago

  • Cc steph@… added

This issue is causing a number of ripple effects. See #8592 and #6939 for starters. All the attempts to patch those problems have apparently incurred some serious performance issues (see Denis's comments on #8592 and #11697).

Would it make sense to pass these functions an extra argument telling them whether or not to include private posts/pages? If the default is to ignore them, everything would work exactly as it does now, but those of us who do need the private pages would have a way to get them (and we'd have to accept the performance hit).

Another way of looking at it: get_pages serves both template (wp_list_pages) and edit screen (wp_dropdown_pages) functions, and it doesn't know which one will use its output. We could pass an argument based on what the user is trying to do. For example, if $user_is = reading (i.e. it's wp_list_pages calling get_pages), we could check to see whether they can see private content and include things accordingly. If they're writing, we could check to see whether they're allowed to edit private pages, and if so, include those pages in the parent dropdown.

#12 in reply to: ↑ 2 @Otto42
8 years ago

  • Priority changed from low to normal
  • Severity changed from minor to normal
  • Type changed from enhancement to defect (bug)
  • Version changed from 2.5 to 2.9.1

Replying to ryan:

get_posts and get_pages should be able to directly retrieve any post status, regardless of the current user. Plugins and the admin need to be able to get at anything. Maybe we need some more args. post_statusin => array('publish', 'private'), check_user_caps => true. Something like that.

Okay, given that, there's still a bug. get_pages cannot retrieve private pages, as it has "post_status = 'publish'" hardcoded in its query.

Seems to me that get_pages is redundant anyway, now. One can simply use get_posts with a argument of 'post_type' => 'page' to get pages. The get_pages function should probably be reworked to just point to get_posts.

#13 @markjaquith
8 years ago

In the dev chat today, people seemed to support Ryan's suggestion of post_status_in and check_user_caps

#14 @Denis-de-Bernardy
7 years ago

  • Keywords bug-hunt added

#15 @Denis-de-Bernardy
7 years ago

  • Keywords featured added; bug-hunt removed

#16 @ryan
7 years ago

WP_Query::get_posts() already supports most of this. get_pages() should call get_posts() and the hierarchical post type bits should go in get_posts() or WP_Query::get_posts().

#17 @nacin
7 years ago

Depending on #12821 I guess.

#18 @sillybean
6 years ago

The patches on #8592 should resolve this problem and #6939.

#19 @nacin
3 years ago

  • Milestone Future Release deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Duplicate of #8592.

Note: See TracTickets for help on using tickets.